/* ================================================================== >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< ------------------------------------------------------------------ Copyright (c) 2019-2023 by Lattice Semiconductor Corporation ALL RIGHTS RESERVED ------------------------------------------------------------------ IMPORTANT: THIS FILE IS USED BY OR GENERATED BY the LATTICE PROPELâ„¢ DEVELOPMENT SUITE, WHICH INCLUDES PROPEL BUILDER AND PROPEL SDK. Lattice grants permission to use this code pursuant to the terms of the Lattice Propel License Agreement. DISCLAIMER: LATTICE MAKES NO WARRANTIES ON THIS FILE OR ITS CONTENTS, WHETHER EXPRESSED, IMPLIED, STATUTORY, OR IN ANY PROVISION OF THE LATTICE PROPEL LICENSE AGREEMENT OR COMMUNICATION WITH LICENSEE, AND LATTICE SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. LATTICE DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED HEREIN WILL MEET LICENSEE 'S REQUIREMENTS, OR THAT LICENSEE' S OPERATION OF ANY DEVICE, SOFTWARE OR SYSTEM USING THIS FILE OR ITS CONTENTS WILL BE UNINTERRUPTED OR ERROR FREE, OR THAT DEFECTS HEREIN WILL BE CORRECTED. LICENSEE ASSUMES RESPONSIBILITY FOR SELECTION OF MATERIALS TO ACHIEVE ITS INTENDED RESULTS, AND FOR THE PROPER INSTALLATION, USE, AND RESULTS OBTAINED THEREFROM. LICENSEE ASSUMES THE ENTIRE RISK OF THE FILE AND ITS CONTENTS PROVING DEFECTIVE OR FAILING TO PERFORM PROPERLY AND IN SUCH EVENT, LICENSEE SHALL ASSUME THE ENTIRE COST AND RISK OF ANY REPAIR, SERVICE, CORRECTION, OR ANY OTHER LIABILITIES OR DAMAGES CAUSED BY OR ASSOCIATED WITH THE SOFTWARE.IN NO EVENT SHALL LATTICE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS FILE OR ITS CONTENTS, EVEN IF LATTICE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. LATTICE 'S SOLE LIABILITY, AND LICENSEE' S SOLE REMEDY, IS SET FORTH ABOVE. LATTICE DOES NOT WARRANT OR REPRESENT THAT THIS FILE, ITS CONTENTS OR USE THEREOF DOES NOT INFRINGE ON THIRD PARTIES' INTELLECTUAL PROPERTY RIGHTS, INCLUDING ANY PATENT. IT IS THE USER' S RESPONSIBILITY TO VERIFY THE USER SOFTWARE DESIGN FOR CONSISTENCY AND FUNCTIONALITY THROUGH THE USE OF FORMAL SOFTWARE VALIDATION METHODS. ------------------------------------------------------------------ ================================================================== */ #include "i3c_target.h" /** * @brief This function is used for I3C target initialization. * @param[in] Passing structure handle : base_addr * base_addr : This parameter specify the I3C target IP base address. * * @return Success or Failure * @exmaple i3c_target_init(handle) */ unsigned int i3c_target_init(struct i3c_target_handle_t *handle) { unsigned int status; if(handle->base_addr != ZERO) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); target->interrupt_1_en=INTERRUPT_ENABLE; // enable the interrupt 1 target->interrupt_2_en=INTERRUPT_ENABLE; // enable the interrupt 2 target->interrupt_3_en=INTERRUPT_ENABLE; // enable the interrupt 3 target->interrupt_4_en=INTERRUPT_ENABLE; // enable the interrupt 4 target->interrupt_5_en=INTERRUPT_ENABLE; // enable the interrupt 5 target->controller_role_handoff=CLEAR; // ack secondary controller request status= SUCCESS; } else { status= FAILURE; } return status; } /** * @brief This function is used for I3C write. * @param[in] Passing structure handle : base_addr, buf and len * base_addr : This parameter specify the I3C target IP base address. * buf : This parameter specify the buffer where data is stored. * len : This parameter specify the length of the buffer. * @return Success or Failure * @exmaple i3c_target_private_write(handle) */ unsigned int i3c_target_private_write(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int max_wr_len; unsigned int wr_len; unsigned char wr_len_msb; unsigned char wr_len_lsb; if((handle->base_addr != ZERO) && (handle->buf != ZERO) && (handle->len != ZERO)) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); wr_len_msb =target->max_wr_legth_msb; wr_len_lsb=target->max_wr_legth_lsb; max_wr_len=(wr_len_msb<len; if (wr_len>max_wr_len) { status = FAILURE; } else { for( int count=ZERO;countlen;++count) // loop wr_length times to send wr_length byte of data { target->tx_fifo=handle->buf[count]; } target->interrupt_2=TX_FIFO_FULL_TGT; status = SUCCESS; } } else { status = FAILURE; } return status; } /** * @brief This function is used for I2C write. * @param[in] Passing structure handle : base_addr, buf and len * base_addr : This parameter specify the I3C target IP base address. * buf : This parameter specify the buffer where data is stored. * len : This parameter specify the length of the buffer. * @return Success or Failure * @exmaple i2c_target_write(handle) */ unsigned int i2c_target_write(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int max_wr_len; unsigned int wr_len; unsigned char wr_len_msb; unsigned char wr_len_lsb; if((handle->base_addr != ZERO) && (handle->buf != ZERO) && (handle->len != ZERO)) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); wr_len_msb =target->max_wr_legth_msb; wr_len_lsb=target->max_wr_legth_lsb; max_wr_len=(wr_len_msb<len; if (wr_len>max_wr_len) { status = FAILURE; } else { for( int count=ZERO;countlen;++count) // loop wr_length times to send wr_length byte of data { target->tx_fifo=handle->buf[count]; } target->interrupt_2=TX_FIFO_FULL_TGT; status = SUCCESS; } } else { status = FAILURE; } return status; } /** * @brief This function is used for I3C private read. * @param[in] Passing structure handle : base_addr, buf and len * base_addr : This parameter specify the I3C target IP base address. * buf : This parameter specify the buffer where data is received. * len : This parameter specify the length of the buffer. * @return Success or Failure * @exmaple i3c_target_private_read(handle) */ unsigned int i3c_target_private_read(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int status_read; unsigned int max_rd_len; unsigned int rd_len; unsigned char rd_len_msb; unsigned char rd_len_lsb; if((handle->base_addr != ZERO) && (handle->buf != ZERO) && (handle->len != ZERO)) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); rd_len_msb =target->max_rd_legth_msb; rd_len_lsb=target->max_rd_legth_lsb; max_rd_len=(rd_len_msb<len; if (rd_len>max_rd_len) { status = FAILURE; } else { do { status_read=target->interrupt_2; }while(!(status_read & RXFIFO_NOTEMPTY)); //check the interrupt status for( int count=ZERO;countlen;++count) // read data upto given length { handle->buf[count]=target->rx_fifo; } target->interrupt_2= RXFIFO_NOTEMPTY; //clear the interrupt status= SUCCESS; } } else { status= FAILURE; } return status; } /** * @brief This function is used for I2C read. * @param[in] Passing structure handle : base_addr, buf and len * base_addr : This parameter specify the I3C target IP base address. * buf : This parameter specify the buffer where data is received. * len : This parameter specify the length of the buffer. * @return Success or Failure * @exmaple i2c_target_read(handle) */ unsigned int i2c_target_read(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int status_read; unsigned int max_rd_len; unsigned int rd_len; unsigned char rd_len_msb; unsigned char rd_len_lsb; if((handle->base_addr != ZERO) && (handle->buf != ZERO) && (handle->len != ZERO)) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); rd_len_msb =target->max_rd_legth_msb; rd_len_lsb=target->max_rd_legth_lsb; max_rd_len=(rd_len_msb<len; if (rd_len>max_rd_len) { status = FAILURE; } else { do { status_read=target->interrupt_2; }while(!(status_read & RXFIFO_NOTEMPTY)); //check the interrupt status for( int count=ZERO;countlen;++count) // read data upto given length { handle->buf[count]=target->rx_fifo; } target->interrupt_2= RXFIFO_NOTEMPTY; //clear the interrupt status= SUCCESS; } } else { status= FAILURE; } return status; } /** * @brief This function is used for I3C HOT JOIN interrupt. * @param[in] Passing structure handle : base_addr, maximum retry * base_addr : This parameter specify the I3c target IP base address. * * maximum retry : This parameter specify number of tries tried by for receiving of ack. * @return Success or Failure * @exmaple : i3c_target_hj_req(handle) */ unsigned int i3c_target_hj_req(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int retBus=ZERO; unsigned int retBusidle=ZERO; unsigned int status_read; unsigned int status_read2; unsigned int dynamic_address; if(handle->base_addr !=ZERO) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); if (!(((target->event_command_en) & HJ_ENABLE)&((target->event_command_dev_config) & HJ_CAPABLE))) // get the device configuartion capabilities status { status=FAILURE; } else { do //wait for bus idle/available { retBus=((target->interrupt_3) & BUSAVL); retBusidle=((target->interrupt_3) & BUSIDLE); }while(!(retBus|retBusidle)); target->event_command_req = EC_REQ_HJ; // generated the request do { //wait for hot join request status_read=target->interrupt_1; }while(!(status_read & HJ_REQ_STATUS)); target->event_command_req |= EC_REQ_HJ; // clear the request interrupt target->interrupt_1 |=HJ_REQ_STATUS; //clear interrupt for(int count=ZERO;countmax_retry;++count) //get the number of retry count { status_read=target->interrupt_1; if(!(status_read & HJ_NACK) ) { do //wait for the hj_done status { status_read2=target->interrupt_1; }while(!(status_read2 & HJ_DONE)); break; } } target->interrupt_1|=HJ_DONE; //clear the interrupt status=SUCCESS; } } else { status = FAILURE; } return status; } /** * @brief This function is used for I3C IBI interrupt. * @param[in] Passing structure handle : base_addr, mandatory data bytes (mdb), optional payload, paylaod legth, maximum retry * base_addr : This parameter specify the I3c target IP base address. * mandatory data bytes (mdb), optional payload, paylaod legth : These parameters is used by user when mdb is capable. * maximum retry : This parameter specify number of tries tried by for receiving of ack. * @return Success or Failure * @exmaple : i3c_target_ibi_req(handle) */ unsigned int i3c_target_ibi_req(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int status_read; unsigned int retBus=ZERO; unsigned int retBusidle=ZERO; if(handle->base_addr !=ZERO) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); if((target->interrupt_1) & IBI_PAYLD_ERR) //check IBI payload error status { target->soft_reset=RST_TXFIFO; } if (target->bcr & BCR_BIT2) // check the BCR second bit = 0 or 1 { if(handle->ibi_optional_payload_len+1<=target->max_ibi_payload) { target->tx_fifo=handle->mdb; //mdb user defind for interrupt for(int count=0;countibi_optional_payload_len;count++) // write the data in txfifo { target->tx_fifo=handle->ibi_optional_payload[count]; } } else { status=FAILURE; } } if (!(((target->event_command_en) & IBI_ENABLE)&((target->event_command_dev_config) & IBI_CAPABLE))) { status = FAILURE; } else { do { //check the bus idle and available condition retBus=((target->interrupt_3) & BUSAVL); retBusidle=((target->interrupt_3) & BUSIDLE); }while(!(retBus|retBusidle)); do { // check the request generated status is 0x08 target->event_command_req = EC_REQ_IBI; // generated the request status_read=target->interrupt_1; }while(status_read!=IBI_REQ_STATUS); //IBI_REQ_STATUS 0x08 target->event_command_req |= EC_REQ_IBI; // clear the request target->interrupt_1|=IBI_REQ_STATUS; //clear the interrupt for(int count=ZERO;count<(handle->max_retry);++count) //get the number of retry count { status_read=target->interrupt_1; if (!((target->interrupt_1) & IBI_NACK)) //acked by the controller { do { status_read=target->interrupt_1; }while(!(status_read & IBI_DONE)); status=SUCCESS; break; } } target->interrupt_1|=IBI_DONE; //clear interrupt } } return status; } /** * @brief This function is used for secondary controller request of I3C target. * @param[in] Passing structure handle : base_addr, maximum retry * base_addr : This parameter specify the I3C target IP base address. * maximum retry : This parameter specify number of tries tried by for receiving of ack. * @return Success or Failure * @exmaple : 3c_target_cntrl_role_handoff (handle) */ unsigned int i3c_target_cntrl_role_handoff(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int status_read; unsigned int status_read2; unsigned int retBus=ZERO; unsigned int retBusidle=ZERO; if(handle->base_addr != ZERO) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); if ((target->event_command_en) & EC_EN_CNTRL_ROLE) // check control register { do { //check the bus idle and available condition retBus=((target->interrupt_3) & BUSAVL); retBusidle=((target->interrupt_3) & BUSIDLE); }while(!(retBus|retBusidle)); do { // check the request generated status is 0x08 target->event_command_req=CNTRL_REQ ; // generated the request status_read=target->interrupt_4; }while(!(status_read & CNTRL_REQ_GEN)); status_read=target->getmxds_con_cap_lsb; status_read=target->controller_role_handoff; target->event_command_req|=CNTRL_REQ; // cleared the request target->interrupt_4 |=CNTRL_REQ_GEN; // clear the generated status for(int count=ZERO;countmax_retry;++count) //get the number of retry count { do { status_read=target->interrupt_4; } while((status_read & CNTRL_REQ_NACK) ); do //wait for the hj_done status { status_read2=target->interrupt_4; }while(!(status_read2 & CNTRL_ROLE_DONE)); status=SUCCESS; break; } target->interrupt_4|=CNTRL_ROLE_DONE; //clear the interrupt } else { status=FAILURE; } } else { status = FAILURE; } return status; } /** * @brief This function is used for I3C hdrddr write. * @param[in] Passing structure handle : base_addr, buf and len * base_addr : This parameter specify the I3C target IP base address. * buf : This parameter specify the buffer where data is stored. * len : This parameter specify the length of the buffer. * @return Success or Failure * @exmaple i3c_target_hdrddr_write(handle) */ unsigned int i3c_target_hdrddr_write(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int max_wr_len; unsigned int wr_len; unsigned char wr_len_msb; unsigned char wr_len_lsb; if((handle->base_addr != ZERO) && (handle->buf != ZERO) && (handle->len != ZERO)) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); wr_len_msb =target->max_wr_legth_msb; wr_len_lsb=target->max_wr_legth_lsb; max_wr_len=(wr_len_msb<len; if (wr_len>max_wr_len) { status = FAILURE; } else { for( int count=ZERO;countlen;count++) // loop wr_length times to send wr_length byte of data { target->tx_fifo=handle->buf[count]; } target->interrupt_2=TX_FIFO_FULL_TGT; status = SUCCESS; } } else { status = FAILURE; } return status; } /** * @brief This function is used for I3C hdrddr read. * @param[in] Passing structure handle : base_addr, buf and len * base_addr : This parameter specify the I3C target IP base address. * buf : This parameter specify the buffer where data is received. * len : This parameter specify the length of the buffer. * @return Success or Failure * @exmaple i3c_target_hdrddr_read(handle) */ unsigned int i3c_target_hdrddr_read(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int status_read; unsigned int max_rd_len; unsigned int rd_len; unsigned char rd_len_msb; unsigned char rd_len_lsb; if((handle->base_addr != ZERO) && (handle->buf != ZERO) && (handle->len != ZERO)) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); rd_len_msb =target->max_rd_legth_msb; rd_len_lsb=target->max_rd_legth_lsb; max_rd_len=(rd_len_msb<len; if (rd_len>max_rd_len) { status = FAILURE; } else { do { status_read=target->interrupt_2; }while(!(status_read & RXFIFO_NOTEMPTY)); //check the interrupt status for( int count=ZERO;countlen;count++) // read data upto given length { handle->buf[count]=target->rx_fifo; } target->interrupt_2= RXFIFO_NOTEMPTY; //clear the interrupt status= SUCCESS; } } else { status= FAILURE; } return status; } /** * @brief This function is used for loop back enable of I3C target. * @param[in] Passing structure handle : base_addr * base_addr : This parameter specify the I3C target IP base address. * @return Success or Failure * @exmaple : i3c_fifo_loopback_enable(handle) */ unsigned int i3c_target_fifo_loopback_enable(struct i3c_target_handle_t *handle) { unsigned int status; if(handle->base_addr != ZERO) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); target->target_response=FIFO_LOOPBACK_EN; status = SUCCESS; } else { status = FAILURE; } return status; } /** * @brief This function is used for waiting of dynamic address assignment of I3C target. * @param[in] Passing structure handle : base_addr * base_addr : This parameter specify the I3C target IP base address. * @return Success or Failure * @exmaple : i3c_target_daa_wait(handle) */ unsigned int i3c_target_daa_wait(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int dynamic_address; if(handle->base_addr != ZERO) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); do { dynamic_address=target->dyn_addr; //read the dynamic address }while(!dynamic_address); status = SUCCESS; } else { status = FAILURE; } return status; } /** * @brief This function is used for waiting of static address assignment of I3C target. * @param[in] Passing structure handle : base_addr * base_addr : This parameter specify the I3C target IP base address. * @return Success or Failure * @exmaple : i3c_target_static_addr_wait(handle) */ unsigned int i3c_target_static_addr_wait(struct i3c_target_handle_t *handle) { unsigned int status; unsigned int static_address; if(handle->base_addr != ZERO) { i3c_tgt_reg_type_t *target = (i3c_tgt_reg_type_t *) (handle->base_addr); do { static_address=target->static_addr; //read the dynamic address }while(!static_address); status = SUCCESS; } else { status = FAILURE; } return status; }