/**
 * @file hv_cal_I2c.c
 * @brief i2c driver chip abstract layer file.
 * @details This file provides the following functions: \n
 *          (1) i2c master tx/rx \n
 *          (2) i2c savle tx/rx \n
 *          (3) i2c init \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2023-05-08
 * @copyright Copyright(c),2023-5, Hiview Software. All rights reserved.
 * @par History:
 * <table>
 * <tr><th>Author       <th>Date            <th>Change Description
 * <tr><td>HiView SoC Software Team     <td>2023-05-08      <td>init
 * </table>
 */
#include "Common/hv_comm_DataType.h"
#include "hv_comm_Define.h"
#include "hv_cal_I2c.h"
#include "hv_cal_Dma.h"
#include "hv_chip_Config.h"
#include "hv_vos_Comm.h"
#include "hv_comm_Define.h"
#include "hv_comm_Assert.h"

#define I2C_BUFF_SIZE 32

#define I2C_FIFO_DEPTH                   16
#define I2C_TIMEOUT                      1000

#define I2C_FLAG_BUSY                           ((UINT32)0x00010001)
#define I2C_FLAG_RX_UNDER                       ((UINT32)0x00000001)
#define I2C_FLAG_RX_OVER                        ((UINT32)0x00000002)
#define I2C_FLAG_RX_FULL                        ((UINT32)0x00000004)
#define I2C_FLAG_TX_OVER                        ((UINT32)0x00000008)
#define I2C_FLAG_TX_EMPTY                       ((UINT32)0x00000010)
#define I2C_FLAG_RD_REQ                         ((UINT32)0x00000020)
#define I2C_FLAG_TX_ABRT                        ((UINT32)0x00000040)
#define I2C_FLAG_RD_DONE                        ((UINT32)0x00000080)
#define I2C_FLAG_ACTIVITY                       ((UINT32)0x00000100)
#define I2C_FLAG_STOP_DEF                       ((UINT32)0x00000200)

#define I2C_DMA_TX_ENABLE                       ((UINT32)0x00000001)
#define I2C_DMA_TX_DISABLE                      ((UINT32)0x00000000)
#define I2C_DMA_RX_ENABLE                       ((UINT32)0x00000001)
#define I2C_DMA_RX_DISABLE                      ((UINT32)0x00000000)
#define I2C_DMA_RDLR                            ((UINT32)0x00000000)
#define I2C_DMA_TDLR                            ((UINT32)0x00000001)

#define GET_I2C_SPEED_50K_H_CNT(x)               (x/24000000*230)
#define GET_I2C_SPEED_50K_L_CNT(x)               (x/24000000*230)
#define GET_I2C_SPEED_80K_H_CNT(x)               (x/24000000*140)
#define GET_I2C_SPEED_80K_L_CNT(x)               (x/24000000*140)
#define GET_I2C_SPEED_100K_H_CNT(x)              ((UINT32)((x / 1000 * 4000 + 500000) / 1000000) - 3)
#define GET_I2C_SPEED_100K_L_CNT(x)              ((UINT32)((x / 1000 * 4700 + 500000) / 1000000) - 1)
#define GET_I2C_SPEED_200K_H_CNT(x)              (x/24000000*50)
#define GET_I2C_SPEED_200K_L_CNT(x)              (x/24000000*50)
#define GET_I2C_SPEED_400K_H_CNT(x)              (((x / 1000 * 600  + 500000) / 1000000) - 3)
#define GET_I2C_SPEED_400K_L_CNT(x)              (((x / 1000 * 1300 + 500000) / 1000000) - 1)

static HvCalI2c s_stI2c[I2C_PORT_MAX];

static BOOL s_bI2cBufUsed = HV_FALSE;
static UCHAR8 g_aucI2CRxBuf[I2C_BUFF_SIZE] = {0};
static UCHAR8 g_ucI2CBufIndex = 0;


static UCHAR8 I2C_GetFlag(HvCalI2c *pstSelf, UINT32 uiFlagBit)
{
    UINT32 uiValue = 0;

    if ((uiFlagBit >> 16) == 0)
    {
        uiValue = HV_R32(CPU_SYS_I2C0_IC_RAW_INTR_STAT + pstSelf->uiBaseOffset);
    }
    else
    {
        uiValue = HV_R32(CPU_SYS_I2C0_IC_STATUS + pstSelf->uiBaseOffset);
    }
    return (uiValue & uiFlagBit & I2C_FLAG_MASK) == (uiFlagBit & I2C_FLAG_MASK);
}

static UCHAR8 I2C_IntSelectEn(HvCalI2c *pstSelf, UINT32 uiIntFlag)
{
    UINT32 uiIntFlagRegVal = 0;

    uiIntFlagRegVal = HV_R32(CPU_SYS_I2C0_IC_INTR_MASK + pstSelf->uiBaseOffset);
    uiIntFlagRegVal = uiIntFlagRegVal | (uiIntFlag & I2C_FLAG_MASK);

    HV_W32(CPU_SYS_I2C0_IC_INTR_MASK + pstSelf->uiBaseOffset, uiIntFlagRegVal);

    return HV_SUCCESS;
}

static UCHAR8 I2C_IntSelectDis(HvCalI2c *pstSelf, UINT32 uiIntFlag)
{

    UINT32 uiIntFlagRegVal = 0;

    uiIntFlagRegVal = HV_R32(CPU_SYS_I2C0_IC_INTR_MASK + pstSelf->uiBaseOffset);
    uiIntFlagRegVal = uiIntFlagRegVal & (~(uiIntFlag & I2C_FLAG_MASK));

    HV_W32(CPU_SYS_I2C0_IC_INTR_MASK + pstSelf->uiBaseOffset, uiIntFlagRegVal);

    return HV_SUCCESS;
}


/** Set i2c transfer speed
 *  @param pstSelf i2c handler
 *  @param enI2cSpeed i2c transfer speed
 */
void Hv_Cal_I2C_Setpeed(HvCalI2c *pstSelf, I2cSpeed enI2cSpeed)
{

    UINT32 HucCountVal = 0;
    UINT32 LucCountVal = 0;

    /* Disable i2c*/
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
    if (enI2cSpeed > I2C_SPEED_100K)
    {
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_CON, pstSelf->uiBaseOffset, SPEED, 2);
    }
    else
    {
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_CON, pstSelf->uiBaseOffset, SPEED, 1);
    }

    if (enI2cSpeed == I2C_SPEED_50K)
    {
        //empirical uiValueue
        HucCountVal = GET_I2C_SPEED_50K_H_CNT(HV_CHIP_CLK_AHB);
        LucCountVal = GET_I2C_SPEED_50K_L_CNT(HV_CHIP_CLK_AHB);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_SS_SCL_HCNT,  pstSelf->uiBaseOffset, IC_SS_SCL_HCNT, HucCountVal);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_SS_SCL_LCNT,  pstSelf->uiBaseOffset, IC_SS_SCL_LCNT, LucCountVal);
    }
    else if (enI2cSpeed == I2C_SPEED_80K)
    {
        //empirical uiValueue
        HucCountVal = GET_I2C_SPEED_80K_H_CNT(HV_CHIP_CLK_AHB);
        LucCountVal = GET_I2C_SPEED_80K_L_CNT(HV_CHIP_CLK_AHB);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_SS_SCL_HCNT,  pstSelf->uiBaseOffset, IC_SS_SCL_HCNT, HucCountVal);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_SS_SCL_LCNT,  pstSelf->uiBaseOffset, IC_SS_SCL_LCNT, LucCountVal);
    }
    else if (enI2cSpeed == I2C_SPEED_100K)
    {
        //empirical uiValueue
        HucCountVal = GET_I2C_SPEED_100K_H_CNT(HV_CHIP_CLK_AHB);
        LucCountVal = GET_I2C_SPEED_100K_L_CNT(HV_CHIP_CLK_AHB) ;
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_SS_SCL_HCNT,  pstSelf->uiBaseOffset, IC_SS_SCL_HCNT, HucCountVal);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_SS_SCL_LCNT,  pstSelf->uiBaseOffset, IC_SS_SCL_LCNT, LucCountVal);
    }
    else if (enI2cSpeed == I2C_SPEED_200K)
    {
        //empirical uiValueue
        HucCountVal = GET_I2C_SPEED_200K_H_CNT(HV_CHIP_CLK_AHB);
        LucCountVal = GET_I2C_SPEED_200K_L_CNT(HV_CHIP_CLK_AHB);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_FS_SCL_HCNT,  pstSelf->uiBaseOffset, IC_FS_SCL_HCNT, HucCountVal);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_FS_SCL_LCNT,  pstSelf->uiBaseOffset, IC_FS_SCL_LCNT, LucCountVal);
    }
    else if (enI2cSpeed == I2C_SPEED_400K)
    {
        HucCountVal = GET_I2C_SPEED_400K_H_CNT(HV_CHIP_CLK_AHB);
        LucCountVal = GET_I2C_SPEED_400K_L_CNT(HV_CHIP_CLK_AHB);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_FS_SCL_HCNT,  pstSelf->uiBaseOffset, IC_FS_SCL_HCNT, HucCountVal);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_FS_SCL_LCNT,  pstSelf->uiBaseOffset, IC_FS_SCL_LCNT, LucCountVal);
    }
    return;
}

static void I2C_ConfigDmaTxReg(HvCalI2c *self, UINT32 EnFlag, UINT32 I2cDmaTxThres)
{
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE,  self->uiBaseOffset, ENABLE, 0);
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_DMA_CR, self->uiBaseOffset, TDMAE, EnFlag);
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_DMA_TDLR, self->uiBaseOffset, DMATDL, I2cDmaTxThres);
}

static void I2C_ConfigDmaRxReg(HvCalI2c *self, UINT32 EnFlag, UINT32 I2cDmaRxThres)
{
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE,  self->uiBaseOffset, ENABLE, 0);
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_DMA_CR, self->uiBaseOffset, RDMAE, EnFlag);
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_DMA_RDLR, self->uiBaseOffset, DMARDL, I2cDmaRxThres);
}

static Status I2C_WaitOnFlagUntilTimeout(HvCalI2c * pstSelf, UINT32 uiFlag, UINT32 uiStatus, UINT32 uiTimeout)
{
    if (uiStatus == 1)
    {
        while(I2C_GetFlag(pstSelf, uiFlag) == 0);
    }
    else
    {
        while(I2C_GetFlag(pstSelf, uiFlag) == 1);
    }

    return HV_SUCCESS;
}

static void I2ctop(HvCalI2c *pstSelf)
{
    UINT32 uiIntFlag = 0;
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;

    if (pstSelf->enInitParam.enMode == I2C_MODE_MASTER)
    {
        /*TODO Add*/
    }
    else
    {
        pstSelf->enState = I2C_STATE_READY;
        pstSelf->enTransCompleteFlag = I2C_TRANS_END;

        uiIntFlag = I2C_FLAG_TX_OVER  | I2C_FLAG_TX_EMPTY| I2C_FLAG_TX_ABRT | I2C_FLAG_RD_REQ
                  | I2C_FLAG_STOP_DEF | I2C_FLAG_RX_FULL | I2C_FLAG_RX_OVER | I2C_FLAG_RX_UNDER | I2C_FLAG_RESTART_DEF;
        I2C_IntSelectDis(pstSelf, uiIntFlag);

        /*Clear Interrupt status flag*/
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);

        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
    }
    return;
}

void I2C_SetDmaTx(HvCalI2c *self, DmaSelf *hdmaTx)
{
    self->hdmaTx = hdmaTx;
    Hv_Cal_Dma_SetParent(hdmaTx,(void*)self);
    Hv_Cal_Dma_SetDstAddr(hdmaTx,CPU_SYS_I2C0_IC_DATA_CMD + self->uiBaseOffset);
}

void I2C_SetDmaRx(HvCalI2c *self, DmaSelf *hdmaRx)
{
    self->hdmaRx = hdmaRx;
    Hv_Cal_Dma_SetParent(hdmaRx,(void*)self);
    Hv_Cal_Dma_SetSrcAddr(hdmaRx,CPU_SYS_I2C0_IC_DATA_CMD + self->uiBaseOffset);
}

static Status I2C_IntTransmitCplt(HvCalI2c *pstSelf)
{
    if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
    {
        return HV_FAILURE;
    }

    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
    pstSelf->enState = I2C_STATE_READY;
    pstSelf->enTransCompleteFlag = I2C_TRANS_END;
    
    return HV_SUCCESS;
}

static Status I2C_IntReceiveCplt(HvCalI2c *pstSelf)
{
    if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
    {
        return HV_FAILURE;
    }

    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
    pstSelf->enState = I2C_STATE_READY;
    pstSelf->enTransCompleteFlag = I2C_TRANS_END;
    if (pstSelf->enInitParam.bNewInterface)
    {
        pstSelf->pucRxBuff      = g_aucI2CRxBuf;
        pstSelf->usRxferCount   = g_ucI2CBufIndex;
        pstSelf->enInitParam.fI2cCpltCallback(I2C_SLAVE_RECEIVE,(void*)pstSelf);
        g_ucI2CBufIndex = 0;
        Hv_Cal_I2C_SlaveIntReceiveEnable(pstSelf->enInitParam.enPort);
    }
    
    return HV_SUCCESS;
}

static Status I2C_MasterDmaTransmitCpltCallback(DmaSelf* arg)
{
    HvCalI2c *self = (HvCalI2c *)Hv_Cal_Dma_GetParent(arg);
    rs_cpu_sys_i2c0_ic_data_cmd  regDataCmdVal = {0};

    if(self->enState == I2C_STATE_BUSY_TX)
    {
        regDataCmdVal.STOP = 1;
        regDataCmdVal.DAT = self->pucTxBuff[self->usTxferSize - 1];
        HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + self->uiBaseOffset, regDataCmdVal);

        if(I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_STOP_DEF, HV_SET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }
        HV_R32(CPU_SYS_I2C0_IC_CLR_STOP_DET + self->uiBaseOffset);
        if(I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }

        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, self->uiBaseOffset, ENABLE, 0);            /* Disable i2c*/
        I2C_ConfigDmaTxReg(self, I2C_DMA_TX_DISABLE, I2C_DMA_TDLR);
        Hv_Cal_Dma_XferCallbackUnBond(self->hdmaTx);
        self->enState = I2C_STATE_READY;
        self->enTransCompleteFlag = I2C_TRANS_END;
        Hv_Vos_InvalidAllDCache();
    }
    else if (self->enState == I2C_STATE_BUSY_TXRX)
    {
        regDataCmdVal.DAT = self->pucTxBuff[self->usTxferSize - 1];
        HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + self->uiBaseOffset, regDataCmdVal);
        regDataCmdVal.STOP = 1;
        regDataCmdVal.CMD = 1;
        regDataCmdVal.DAT = 0;
        HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + self->uiBaseOffset, regDataCmdVal);
    }
    

    return HV_SUCCESS;
}

static Status I2C_MasterDmaReceiveCpltCallback(DmaSelf* arg)
{
    HvCalI2c *self = (HvCalI2c *)Hv_Cal_Dma_GetParent(arg);
    if(I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_STOP_DEF, HV_SET, I2C_TIMEOUT) != HV_SUCCESS)
    {
        return HV_FAILURE;
    }
    HV_R32(CPU_SYS_I2C0_IC_CLR_STOP_DET + self->uiBaseOffset);                                      /*Clear Stop*/
    if(I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
    {
        return HV_FAILURE;
    }
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, self->uiBaseOffset, ENABLE, 0);                          /* Disable i2c*/
    I2C_ConfigDmaTxReg(self, I2C_DMA_TX_DISABLE, I2C_DMA_TDLR);
    I2C_ConfigDmaRxReg(self, I2C_DMA_RX_DISABLE, I2C_DMA_RDLR);
    Hv_Cal_Dma_XferCallbackUnBond(self->hdmaRx);
    self->enState = I2C_STATE_READY;
    self->enTransCompleteFlag = I2C_TRANS_END;
    Hv_Vos_InvalidAllDCache();
    
    return HV_SUCCESS;
}


static Status I2C_SlaveDmaTransmitCpltCallback(DmaSelf* arg)
{
    HvCalI2c *self = (HvCalI2c *)Hv_Cal_Dma_GetParent(arg);
    if(I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
    {
        return HV_FAILURE;
    }
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, self->uiBaseOffset, ENABLE, 0);
    I2C_ConfigDmaTxReg(self, I2C_DMA_TX_DISABLE, I2C_DMA_TDLR);
    Hv_Cal_Dma_XferCallbackUnBond(self->hdmaTx);
    self->enState = I2C_STATE_READY;
    self->enTransCompleteFlag = I2C_TRANS_END;
    Hv_Vos_InvalidAllDCache();
    
    return HV_SUCCESS;
}

static Status I2C_SlaveDmaReceiveCpltCallback(DmaSelf* arg)
{
    HvCalI2c *self = (HvCalI2c *)Hv_Cal_Dma_GetParent(arg);
    if(I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
    {
        return HV_FAILURE;
    }
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, self->uiBaseOffset, ENABLE, 0);      /* Disable i2c*/
    I2C_ConfigDmaRxReg(self, I2C_DMA_RX_DISABLE, I2C_DMA_RDLR);
    Hv_Cal_Dma_XferCallbackUnBond(self->hdmaRx);
    self->enState = I2C_STATE_READY;
    self->enTransCompleteFlag = I2C_TRANS_END;
    Hv_Vos_InvalidAllDCache();
    
    return HV_SUCCESS;
}

static Status I2C_MasterIntTransmitHandler(HvCalI2c *pstSelf)
{
    UINT32 uiLoop = 0;
    UCHAR8  ucDummy = 0;
    UINT32 uiTxFifoSurplusLev = 0;
    UINT32 uTxDataNumOnce = 0;
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UCHAR8* pucCmdAddr = NULL;
    UCHAR8* pucTxData = NULL;
    UINT32 uiIntFlag = 0;
    UINT32 uiTxTotalSize = pstSelf->usCmdAddrSize + pstSelf->usTxferSize;
    rs_cpu_sys_i2c0_ic_data_cmd regDataCmdVal = {0};

    if (pstSelf->enState == I2C_STATE_BUSY_TX)
    {
        regDataCmdVal.CMD = 0;
        pucCmdAddr = pstSelf->pucCmdAddr;
        if (pstSelf->usTxferSize > 0)
        {
            pucTxData = &(pstSelf->pucTxBuff[pstSelf->usTxferCount]);
        }
    }
    else if (pstSelf->enState == I2C_STATE_BUSY_TXRX)
    {
        regDataCmdVal.CMD = 0;
        pucCmdAddr = pstSelf->pucCmdAddr;
    }
    else
    {
        ;
    }

    uiTxFifoSurplusLev = I2C_FIFO_DEPTH - HV_R32(CPU_SYS_I2C0_TXFLR + uiBaseOffset);
    if (uiTxTotalSize >= uiTxFifoSurplusLev)
    {
        uTxDataNumOnce = uiTxFifoSurplusLev;
    }
    else
    {
        uTxDataNumOnce = uiTxTotalSize;
    }

    for (uiLoop = 0; uiLoop < uTxDataNumOnce; uiLoop++)
    {
        if ((uiTxTotalSize == 1) && (pstSelf->enState != I2C_STATE_BUSY_TXRX))
        {
            regDataCmdVal.STOP = 1;
        }
        if (pstSelf->usCmdAddrSize > 0)
        {
            regDataCmdVal.DAT = (*pucCmdAddr++);
            pstSelf->usCmdAddrSize--;
            if ((pstSelf->usCmdAddrSize == 0) && (pstSelf->enState == I2C_STATE_BUSY_TXRX))
            {
                pstSelf->enState = I2C_STATE_BUSY_RX;
            }
        }
        else
        {
            if (pstSelf->enState == I2C_STATE_BUSY_TX)
            {
                regDataCmdVal.DAT = (*pucTxData++);
                pstSelf->usTxferCount++;
            }
            else if (pstSelf->enState == I2C_STATE_BUSY_RX)
            {
                regDataCmdVal.CMD = 1;
                regDataCmdVal.DAT = ucDummy;
            }
            pstSelf->usTxferSize--;
        }

        HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset, regDataCmdVal);
        uiTxTotalSize = pstSelf->usCmdAddrSize + pstSelf->usTxferSize;
    }

    if (uiTxTotalSize == 0)
    {

        if (pstSelf->enState == I2C_STATE_BUSY_TX)
        {
            uiIntFlag = I2C_FLAG_TX_OVER | I2C_FLAG_TX_EMPTY | I2C_FLAG_TX_ABRT | I2C_FLAG_MASTER_ON_HOLD | I2C_FLAG_STUCK_AT_LOW;
            I2C_IntSelectDis(pstSelf, uiIntFlag);
            I2C_IntTransmitCplt(pstSelf);
        }
        else if (pstSelf->enState == I2C_STATE_BUSY_RX)
        {
            uiIntFlag = I2C_FLAG_TX_OVER | I2C_FLAG_TX_EMPTY | I2C_FLAG_TX_ABRT;
            I2C_IntSelectDis(pstSelf, uiIntFlag);
        }
    }
    return HV_SUCCESS;
}

static Status I2C_MasterIntReceiveHandler(HvCalI2c *pstSelf)
{

    UINT32 uiLoop = 0;
    UINT32 uiIntFlag = 0;
    UINT32 uiRxFifoDataLev = 0;
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UCHAR8* pucRxData = &(pstSelf->pucRxBuff[pstSelf->usRxferCount]);

    uiRxFifoDataLev = HV_R32(CPU_SYS_I2C0_RXFLR + pstSelf->uiBaseOffset);
    for (uiLoop = 0; uiLoop < uiRxFifoDataLev; uiLoop++)
    {
        *pucRxData = HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
        pucRxData = pucRxData + 1;
        pstSelf->usRxferSize--;
        pstSelf->usRxferCount++;
    }
    if (pstSelf->usRxferSize == 0)
    {
        uiIntFlag = I2C_FLAG_MASTER_ON_HOLD | I2C_FLAG_STUCK_AT_LOW | I2C_FLAG_RX_FULL | I2C_FLAG_RX_OVER | I2C_FLAG_RX_UNDER;
        I2C_IntSelectDis(pstSelf, uiIntFlag);
        I2C_IntReceiveCplt(pstSelf);
    }
    return HV_SUCCESS;
}


static Status I2C_SlaveIntTransmitHandler(HvCalI2c *pstSelf) {

    UINT32 uiIntFlag = 0;
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UCHAR8* pucTxData = &(pstSelf->pucTxBuff[pstSelf->usTxferCount]);
    rs_cpu_sys_i2c0_ic_data_cmd regDataCmdVal = {0};
    UCHAR8 ucTxFifoDataLev = 0;
    UCHAR8 ucTxThisTime = 0;
    UCHAR8 ucCount = 0;
    HV_R32_DECL_VAR();

    if (I2C_GetFlag(pstSelf, I2C_FLAG_TX_ABRT) == 1)
    {
        HV_R32(CPU_SYS_I2C0_IC_CLR_TX_ABRT + uiBaseOffset);
    }


    ucTxFifoDataLev = HV_R32_FIELD_EX(CPU_SYS_I2C0_TXFLR, pstSelf->uiBaseOffset, TXFLR);
    /* TX_TL is I2C_FIFO_DEPTH / 2 */
    ucTxThisTime = ((I2C_FIFO_DEPTH) - ucTxFifoDataLev);
    ucTxThisTime = (ucTxThisTime < pstSelf->usTxferSize) ? ucTxThisTime : pstSelf->usTxferSize;

    for (ucCount = 0; ucCount < ucTxThisTime; ucCount++)
    {
        regDataCmdVal.DAT = *(pucTxData + ucCount);
        HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset, regDataCmdVal);
        pstSelf->usTxferSize--;
        pstSelf->usTxferCount++;
    }

    /* Clear read request flag*/
    HV_R32(CPU_SYS_I2C0_IC_CLR_RD_REQ + uiBaseOffset);

    return HV_SUCCESS;
}

static Status I2C_TxAbrtHandler(HvCalI2c *pstSelf)
{
    I2ctop(pstSelf);
    if (pstSelf->enInitParam.fI2cCpltCallback != NULL)
    {
        pstSelf->enInitParam.fI2cCpltCallback(I2C_ABRT_TRANSMIT,(void*)pstSelf);
    }
    return HV_SUCCESS;
}

static Status I2C_SlaveIntReceiveHandler(HvCalI2c *pstSelf)
{
    UINT32 uiLoop = 0;
    UINT32 uiIntFlag = 0;
    UINT32 uiRxFifoDataLev = 0;
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UCHAR8* pucRxData = &(pstSelf->pucRxBuff[pstSelf->usRxferCount]);

    uiRxFifoDataLev = HV_R32(CPU_SYS_I2C0_RXFLR + pstSelf->uiBaseOffset);

    for(uiLoop = 0; uiLoop < uiRxFifoDataLev; uiLoop++)
    {
        if (pstSelf->enInitParam.bNewInterface)
        {
            g_aucI2CRxBuf[(g_ucI2CBufIndex++)%I2C_BUFF_SIZE] = HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
        }
        else
        {
            *pucRxData++ = HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
            pstSelf->usRxferCount++;
        }
    }
    return HV_SUCCESS;
}

static Status I2C_SlaveIntRestartHandler(HvCalI2c *pstSelf)
{
    UINT32 uiLoop = 0;
    UINT32 uiIntFlag = 0;
    UINT32 uiRxFifoDataLev = 0;
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UCHAR8* pucRxData = &(pstSelf->pucRxBuff[pstSelf->usRxferCount]);

    if ((pstSelf->enInitParam.fI2cCpltCallback == NULL) || (pstSelf->enInitParam.enMode == I2C_MODE_MASTER))
    {
        HV_LOGI("Err:i2c restart\n");
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
        pstSelf->enState = I2C_STATE_READY;
        pstSelf->enTransCompleteFlag = I2C_TRANS_END;
    }

    if ((pstSelf->enInitParam.enMode == I2C_MODE_SLAVE)
        && ((pstSelf->enState == I2C_STATE_BUSY_RX)
            || (HV_TRUE == pstSelf->enInitParam.bNewInterface)))
    {
        pstSelf->enState = I2C_STATE_BUSY_SLAVE_RESTART;
        uiRxFifoDataLev = HV_R32(CPU_SYS_I2C0_RXFLR + pstSelf->uiBaseOffset);
        for (uiLoop = 0; uiLoop < uiRxFifoDataLev; uiLoop++)
        {
            if (pstSelf->enInitParam.bNewInterface)
            {
                g_aucI2CRxBuf[(g_ucI2CBufIndex++)%I2C_BUFF_SIZE] = HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
            }
            else
            {
                *pucRxData++ = HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
                pstSelf->usRxferSize--;
                pstSelf->usRxferCount++;
            }
        }
        if (pstSelf->enInitParam.bNewInterface)
        {
            pstSelf->enInitParam.fI2cCpltCallback(I2C_SLAVE_RESTART,(void*)pstSelf);
        }
        uiIntFlag = I2C_FLAG_RX_FULL | I2C_FLAG_RX_OVER | I2C_FLAG_RX_UNDER | I2C_FLAG_RESTART_DEF | I2C_FLAG_STOP_DEF;
        I2C_IntSelectDis(pstSelf, uiIntFlag);
        //slave callback

        //pstSelf->enInitParam.fI2cCpltCallback(I2C_SLAVE_RESTART,(void*)pstSelf);
    }
    return HV_SUCCESS;
}

static Status I2C_IntStopHandler(HvCalI2c *pstSelf)
{

    UINT32 uiLoop = 0;
    UINT32 uiIntFlag = 0;
    UINT32 uiRxFifoDataLev = 0;
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UCHAR8* pucRxData = &(pstSelf->pucRxBuff[pstSelf->usRxferCount]);

    if ((pstSelf->enInitParam.enMode == I2C_MODE_SLAVE)
         && ((pstSelf->enState == I2C_STATE_BUSY_RX)
             || (HV_TRUE == pstSelf->enInitParam.bNewInterface)))
    {
        uiRxFifoDataLev = HV_R32(CPU_SYS_I2C0_RXFLR + pstSelf->uiBaseOffset);
        for (uiLoop = 0; uiLoop < uiRxFifoDataLev; uiLoop++)
        {
            if (pstSelf->enInitParam.bNewInterface)
            {
                g_aucI2CRxBuf[(g_ucI2CBufIndex++)%I2C_BUFF_SIZE] = HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
            }
            else
            {
                *pucRxData++ = HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
                pstSelf->usRxferSize--;
                pstSelf->usRxferCount++;
            }
        }
        if (pstSelf->enInitParam.bNewInterface)
        {
            pstSelf->enInitParam.fI2cCpltCallback(I2C_SLAVE_STOP,(void*)pstSelf);
        }
        uiIntFlag = I2C_FLAG_RX_FULL | I2C_FLAG_RX_OVER | I2C_FLAG_RX_UNDER;
        I2C_IntSelectDis(pstSelf, uiIntFlag);
        I2C_IntReceiveCplt(pstSelf);
    }
    else if ((pstSelf->enInitParam.enMode == I2C_MODE_SLAVE) && (pstSelf->enState == I2C_STATE_BUSY_TX))
    {
        //if (pstSelf->usTxferSize != 0)
        //{
//            HV_LOGI("Err:i2c tx len\n");
        //}
        uiIntFlag = I2C_FLAG_TX_OVER | I2C_FLAG_TX_EMPTY | I2C_FLAG_TX_ABRT | I2C_FLAG_RD_REQ | I2C_FLAG_STOP_DEF;
        I2C_IntSelectDis(pstSelf, uiIntFlag);
        I2C_IntTransmitCplt(pstSelf);
    }
    return HV_SUCCESS;
}

static HV_VOS_ISR_RESULT_E  HV_CAL_I2C_IrqHandler(UINT32 uiIrqNum, void *arg)
{
    UINT32 uiIntStaVal = 0;
    HvCalI2c *pstSelf = (HvCalI2c *)arg;
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;

    HV_UNUSED(uiIrqNum);
    uiIntStaVal = HV_R32(CPU_SYS_I2C0_IC_INTR_STAT + uiBaseOffset);

    if ((uiIntStaVal & I2C_FLAG_RX_UNDER) == I2C_FLAG_RX_UNDER)
    {
        HV_LOGI("i2c rx under erro.\n");
    }
    if ((uiIntStaVal & I2C_FLAG_RX_OVER) == I2C_FLAG_RX_OVER)
    {
        HV_LOGI("i2c rx over.\n");
    }
    if ((uiIntStaVal & I2C_FLAG_RX_FULL) == I2C_FLAG_RX_FULL)
    {
        if (pstSelf->enInitParam.enMode == I2C_MODE_MASTER)
        {
            I2C_MasterIntReceiveHandler(pstSelf);
        }
        else if(pstSelf->enInitParam.enMode == I2C_MODE_SLAVE)
        {
            I2C_SlaveIntReceiveHandler(pstSelf);
        }
    }

    //if ((uiIntStaVal & I2C_FLAG_RESTART_DEF) == I2C_FLAG_RESTART_DEF)
    //{
//         HV_LOGI("i2c restart.\n");
        //I2C_SlaveIntRestartHandler(pstSelf);
    //}
    if ((uiIntStaVal & I2C_FLAG_TX_OVER) == I2C_FLAG_TX_OVER)
    {
        HV_LOGI("i2c tx over.\n");
    }
    if ((uiIntStaVal & I2C_FLAG_TX_EMPTY) == I2C_FLAG_TX_EMPTY)
    {
        I2C_MasterIntTransmitHandler(pstSelf);
    }
    if ((uiIntStaVal & I2C_FLAG_RD_REQ) == I2C_FLAG_RD_REQ)
    {
        I2C_SlaveIntTransmitHandler(pstSelf);
    }
    if ((uiIntStaVal & I2C_FLAG_TX_ABRT) == I2C_FLAG_TX_ABRT)
    {
//        HV_LOGI("i2c tx abort1:%x.\n",HV_R32(CPU_SYS_I2C0_IC_TX_ABRT_SOURCE + uiBaseOffset));
        I2C_TxAbrtHandler(pstSelf);
    }
    if ((uiIntStaVal & I2C_FLAG_RD_DONE) == I2C_FLAG_RD_DONE)
    {
        HV_LOGI("i2c rd done.\n");
    }
    if ((uiIntStaVal & I2C_FLAG_ACTIVITY) == I2C_FLAG_ACTIVITY)
    {
        HV_LOGI("i2c tx abort2.\n");
    }
    if ((uiIntStaVal & I2C_FLAG_STOP_DEF) == I2C_FLAG_STOP_DEF)
    {
        I2C_IntStopHandler(pstSelf);
    }
    if ((uiIntStaVal & I2C_FLAG_MASTER_ON_HOLD) == I2C_FLAG_MASTER_ON_HOLD)
    {
        HV_LOGI("i2c master on hold.\n");
    }
    //if ((uiIntStaVal & I2C_FLAG_STUCK_AT_LOW) == I2C_FLAG_STUCK_AT_LOW)
    //{
        //HV_LOGI("i2c stuck at low.\n");
    //}
    return (HV_VOS_ISR_RESULT_E)HV_SUCCESS;
}

/** Initialize i2c
 *  @param pstInitParam pointer to i2c configuration parameters
 *  @return i2c handler
 */
HvCalI2c*  Hv_Cal_I2C_Init(I2cInitParam *pstInitParam)
{
    HvCalI2c *pstSelf = NULL;

    rs_cpu_sys_i2c0_ic_con  regConVal = {0};
    rs_cpu_sys_i2c0_ic_sar regSarVal = {0};
    rs_cpu_sys_i2c0_ic_tx_tl  regTxTlVal = {0};
    rs_cpu_sys_i2c0_ic_rx_tl  regRxTlVal = {0};

    HV_ASSERT_PEEK_TRUE(pstInitParam && pstInitParam->enPort < I2C_PORT_MAX);
    pstSelf = &s_stI2c[pstInitParam->enPort];
    if (pstInitParam->enPort == I2C_PORT_0)
    {
        pstSelf->uiBaseOffset = 0;
    }
    else if (pstInitParam->enPort == I2C_PORT_1)
    {
        pstSelf->uiBaseOffset = HV_I2C1_BASE_ADDRESS - HV_I2C0_BASE_ADDRESS;
    }
    if (pstInitParam->bNewInterface)
    {
        //if (HV_TRUE == s_bI2cBufUsed)
        //{
            //HV_LOGE("only support one port with new interface.");
        //}
        if (pstInitParam->fI2cCpltCallback ==  NULL)
        {
            HV_LOGE("new interface without callback.");
        }
        else
        {
            s_bI2cBufUsed = HV_TRUE;
        }
    }

    HV_MEMCPY(&pstSelf->enInitParam, pstInitParam, sizeof(*pstInitParam));
    /* Disable i2c*/
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
    /* Clear interrupt Flag*/
    HV_R32(CPU_SYS_I2C0_IC_CLR_INT + pstSelf->uiBaseOffset);
    /* Mask interrupt*/
    HV_W32(CPU_SYS_I2C0_IC_INTR_MASK + pstSelf->uiBaseOffset, 0x00);

    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_SDA_HOLD, pstSelf->uiBaseOffset, IC_SDA_TX_HOLD, 60); // 300ns

    if (pstInitParam->enMode == I2C_MODE_MASTER)
    {
        regConVal.MASTER_MODE = 1;
        regConVal.IC_SLAVE_DISABLE = 1;
        regConVal.IC_10BITADDR_MASTER = pstInitParam->enAddressingMode;
        regConVal.IC_RESTART_EN = 1;
        regConVal.TX_EMPTY_CTRL = 0;
        regConVal.RX_FIFO_FULL_HLD_CTRL = 1;
        regConVal.BUS_CLEAR_FEATURE_CTRL = 1;

        if (pstInitParam->enSpeed > I2C_SPEED_100K)
        {
            regConVal.SPEED = 2;
        }
        else
        {
            regConVal.SPEED = 1;
        }
        HV_W32_REG(CPU_SYS_I2C0_IC_CON + pstSelf->uiBaseOffset, regConVal);
        Hv_Cal_I2C_Setpeed(pstSelf,pstInitParam->enSpeed);

        regTxTlVal.TX_TL = I2C_FIFO_DEPTH / 2;;
        regRxTlVal.RX_TL = 0;
        HV_W32_REG( CPU_SYS_I2C0_IC_TX_TL + pstSelf->uiBaseOffset, regTxTlVal);
        HV_W32_REG( CPU_SYS_I2C0_IC_RX_TL + pstSelf->uiBaseOffset, regRxTlVal);
    }
    else if (pstInitParam->enMode == I2C_MODE_SLAVE)
    {
        regConVal.MASTER_MODE = 0;
        regConVal.IC_SLAVE_DISABLE = 0;
        regConVal.IC_10BITADDR_SLAVE = pstInitParam->enAddressingMode;
        regConVal.TX_EMPTY_CTRL = 0;
        regConVal.RX_FIFO_FULL_HLD_CTRL = 1;
        regConVal.STOP_DET_IFADDRESSED = 1;
        HV_W32_REG( CPU_SYS_I2C0_IC_CON + pstSelf->uiBaseOffset, regConVal);

        regSarVal.IC_SAR = pstInitParam->OwnAddress;
        HV_W32_REG( CPU_SYS_I2C0_IC_SAR + pstSelf->uiBaseOffset, regSarVal);

        regTxTlVal.TX_TL = I2C_FIFO_DEPTH / 2;;
        regRxTlVal.RX_TL = 0;
        HV_W32_REG( CPU_SYS_I2C0_IC_TX_TL + pstSelf->uiBaseOffset, regTxTlVal);
        HV_W32_REG( CPU_SYS_I2C0_IC_RX_TL + pstSelf->uiBaseOffset, regRxTlVal);
    }

    if (0 == pstSelf->ucInitCount)
    {
        if (pstInitParam->enPort == I2C_PORT_0)
        {
            Hv_Vos_ConfigIrq(HV_CHIP_IRQ_I2C0, HV_TRUE, 0);
            Hv_Vos_AttachIsr(HV_CHIP_IRQ_I2C0, HV_CAL_I2C_IrqHandler, pstSelf);
            Hv_Vos_UnmaskIrq(HV_CHIP_IRQ_I2C0);
        }
        else if(pstInitParam->enPort == I2C_PORT_1)
        {
            Hv_Vos_ConfigIrq(HV_CHIP_IRQ_I2C1, HV_TRUE, 0);
            Hv_Vos_AttachIsr(HV_CHIP_IRQ_I2C1, HV_CAL_I2C_IrqHandler, pstSelf);
            Hv_Vos_UnmaskIrq(HV_CHIP_IRQ_I2C1);
        }
    }

    /* Mask All Interrupt*/
    HV_W32( CPU_SYS_I2C0_IC_INTR_MASK + pstSelf->uiBaseOffset, 0x00);
    /* Clear interrupt Flag*/
    HV_R32(CPU_SYS_I2C0_IC_CLR_INT + pstSelf->uiBaseOffset);
    pstSelf->enErrorCode = I2C_ERROR_NONE;
    pstSelf->enState = I2C_STATE_READY;
    pstSelf->ucInitCount++;

    return pstSelf;
}

/** De-initialize i2c
 *  @param pstSelf i2c handler
 *  @return result
 */
Status Hv_Cal_I2C_Cleanup(HvCalI2c *pstSelf)
{
    pstSelf->enState = I2C_STATE_BUSY;
    if (0 != pstSelf->ucInitCount)
    {
        return HV_SUCCESS;
    }

    /* Disable I2C */
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
    if (pstSelf->enInitParam.enPort == I2C_PORT_0)
    {
        Hv_Vos_MaskIrq(HV_CHIP_IRQ_I2C0);
        Hv_Vos_DetachIsr(HV_CHIP_IRQ_I2C0, HV_CAL_I2C_IrqHandler);
    }
    else if (pstSelf->enInitParam.enPort == I2C_PORT_1)
    {
        Hv_Vos_MaskIrq(HV_CHIP_IRQ_I2C1);
        Hv_Vos_DetachIsr(HV_CHIP_IRQ_I2C1, HV_CAL_I2C_IrqHandler);
    }
    pstSelf->enErrorCode = I2C_ERROR_NONE;
    pstSelf->enState = I2C_STATE_RESET;
    return HV_SUCCESS;
}

/** Transmits in master mode an amount of data in blocking mode.
 *  @param pstSelf i2c handler
 *  @param pstParam, target device address
 *  pointer to command data buffer
 *  command length
 *  pointer to data buffer to be transmited
 *  amount of data to be sent
 *  @param uiTimeout uiTimeout duration
  * @retval Status
 */
Status Hv_Cal_I2C_MasterPollingTransmit(HvCalI2c *pstSelf, I2cFuncParam *pstParam, UINT32 uiTimeout)
{
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    rs_cpu_sys_i2c0_ic_data_cmd  regDataCmdVal = {0};
    rs_cpu_sys_i2c0_ic_tar regTARVal = {0};
    USHORT16 usTxFifoSurpLev = 0;
    USHORT16 usTotalSize = pstParam->usCmdAddrSize + pstParam->usDataSize;
    USHORT16 usTxNumOnce = 0;
    UINT32 uiLoop = 0;
    USHORT16 usCmdAddrSize = pstParam->usCmdAddrSize;
    /* Set direction is write*/
    regDataCmdVal.CMD = 0;
    if (pstSelf->enState == I2C_STATE_READY)
    {
        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            HV_LOGW("Wait master I2C free uiTimeout.\n");
            return HV_FAILURE;
        }

        regTARVal.IC_10BITADDR_MASTER = pstSelf->enInitParam.enAddressingMode;
        regTARVal.IC_TAR = pstParam->usDevAddress;
        /* Normal TAR, No General Call and Start byte*/
        regTARVal.SPECIAL = 0;
        HV_W32_REG(CPU_SYS_I2C0_IC_TAR + pstSelf->uiBaseOffset, regTARVal);
        /*Clear Raw Interrupt status flag*/
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);
        /* Enable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 1);

        pstSelf->enState = I2C_STATE_BUSY_TX;
        pstSelf->enErrorCode = I2C_ERROR_NONE;

        /* This transmits by checking txfifo is empty or not. */
        while (usTotalSize > 0)
        {

            usTxFifoSurpLev = I2C_FIFO_DEPTH - HV_R32(CPU_SYS_I2C0_TXFLR + uiBaseOffset);
            if (usTxFifoSurpLev < usTotalSize)
            {
                usTxNumOnce = usTxFifoSurpLev;
            }
            else
            {
                usTxNumOnce = usTotalSize;
            }

            for (uiLoop = 0; uiLoop < usTxNumOnce; uiLoop++)
            {
                if (usTotalSize == 1)
                {
                    regDataCmdVal.STOP = 1;
                }
                if (usCmdAddrSize > 0)
                {
                    regDataCmdVal.DAT = (*pstParam->pucCmdAddr++);
                    HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset, regDataCmdVal);
                    usCmdAddrSize--;
                }
                else
                {
                    regDataCmdVal.DAT = (*pstParam->pucData++);
                    HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset, regDataCmdVal);
                }
                usTotalSize--;
            }
        }

        /* check if stop already generate*/
        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_STOP_DEF, HV_SET, uiTimeout) != HV_SUCCESS)
        {
            HV_LOGW("Wait master I2C stop uiTimeout.\n");
            return HV_FAILURE;
        }
        /*Clear Stop*/
        HV_R32( CPU_SYS_I2C0_IC_CLR_STOP_DET + uiBaseOffset);
        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, uiTimeout) != HV_SUCCESS)
        {
            HV_LOGW("Wait master I2C busy clear uiTimeout.\n");
            return HV_FAILURE;
        }

        /* Enable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
        pstSelf->enState = I2C_STATE_READY;
        return HV_SUCCESS;
    }
    else
    {
        HV_LOGW("Master I2C busy.\n");
        return HV_FAILURE;
    }
}


/** Transmit in master mode an amount of data in non-blocking mode with interrupt
 *  @param pstSelf i2c handler
 *  @param pstParam, target device address
 *  pointer to command data buffer
 *  command length
 *  pointer to data buffer to be transmited
 *  amount of data to be sent
  * @retval Status
 */
Status Hv_Cal_I2C_MasterIntTransmit(HvCalI2c  *pstSelf, I2cFuncParam *pstParam)
{
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UINT32 uiIntFlag = 0;
    rs_cpu_sys_i2c0_ic_tar regTARVal = {0};

    if (pstSelf->enState == I2C_STATE_READY)
    {
        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }

        pstSelf->pucCmdAddr = pstParam->pucCmdAddr;
        pstSelf->usCmdAddrSize = pstParam->usCmdAddrSize;
        pstSelf->pucTxBuff = pstParam->pucData;
        pstSelf->usTxferSize = pstParam->usDataSize;
        pstSelf->usTxferCount = 0;

        regTARVal.IC_10BITADDR_MASTER = pstSelf->enInitParam.enAddressingMode;
        regTARVal.IC_TAR = pstParam->usDevAddress;
        /* Normal TAR, No General Call and Start byte*/
        regTARVal.SPECIAL = 0;
        HV_W32_REG(CPU_SYS_I2C0_IC_TAR + pstSelf->uiBaseOffset, regTARVal);

        /*Clear Interrupt status flag*/
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);

        uiIntFlag = I2C_FLAG_TX_OVER | I2C_FLAG_TX_EMPTY | I2C_FLAG_TX_ABRT
                    | I2C_FLAG_STOP_DEF | I2C_FLAG_MASTER_ON_HOLD
                    | I2C_FLAG_STUCK_AT_LOW;
        I2C_IntSelectEn(pstSelf, uiIntFlag);

        pstSelf->enState = I2C_STATE_BUSY_TX;
        pstSelf->enErrorCode = I2C_ERROR_NONE;
        pstSelf->enTransCompleteFlag = I2C_TRANS_IN_PROCESS;
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 1);
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

Status Hv_Cal_I2C_MasterDmaTransmit(HvCalI2c  *self, USHORT16 devAddress, UCHAR8* pData, USHORT16 dataSize)
{
    rs_cpu_sys_i2c0_ic_tar regTARVal = {0};
    UINT32 base_offset = self->uiBaseOffset;

    if(self->enState == I2C_STATE_READY)
    {
        if(I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }
        self->pucTxBuff = pData;
        self->usTxferSize = dataSize;

        Hv_Cal_Dma_XferCallbackBond(self->hdmaTx, I2C_MasterDmaTransmitCpltCallback);
        Hv_Cal_Dma_SetSrcFrameSize(self->hdmaTx, DMA_DATA_SIZE_8Bits);
        Hv_Cal_Dma_SetDstFrameSize(self->hdmaTx, DMA_DATA_SIZE_8Bits);
        Hv_Cal_Dma_SetBlockSize(self->hdmaTx, dataSize - 1);

        Hv_Cal_Dma_SetSrcAddr(self->hdmaTx, (UINT32)pData);
        Hv_Cal_Dma_ChannelEn(self->hdmaTx);

        regTARVal.IC_10BITADDR_MASTER = self->enInitParam.enAddressingMode;
        regTARVal.IC_TAR = devAddress;
        regTARVal.SPECIAL = 0;                                                       /* Normal TAR, No General Call and Start byte*/
        HV_W32_REG(CPU_SYS_I2C0_IC_TAR + self->uiBaseOffset, regTARVal);
        I2C_ConfigDmaTxReg(self, I2C_DMA_TX_ENABLE, I2C_DMA_TDLR);

        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + base_offset);                                    /*Clear Raw Interrupt status flag*/
        self->enState = I2C_STATE_BUSY_TX;
        self->enErrorCode = I2C_ERROR_NONE;
        self->enTransCompleteFlag = I2C_TRANS_IN_PROCESS;
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, self->uiBaseOffset, ENABLE, 1);             /* Enable i2c*/
        return HV_SUCCESS;
    } 
    else
    {
        return HV_FAILURE;
    }
}

/** Receives in master mode an amount of data in blocking mode.
 *  @param pstSelf i2c handler
 *  @param pstParam, target device address
 *  pointer to command data buffer
 *  command length
 *  pointer to data buffer to be receive
 *  amount of data to be receive
 *  @param uiTimeout uiTimeout duration
 *  @retval Status
*/
Status Hv_Cal_I2C_MasterPollingReceive(HvCalI2c *pstSelf, I2cFuncParam *pstParam, UINT32 uiTimeout)
{
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    rs_cpu_sys_i2c0_ic_data_cmd  regDataCmdVal = {0};
    rs_cpu_sys_i2c0_ic_tar regTARVal = {0};
    UINT32 usTxFifoSurpLev = 0;
    UINT32 uiRxFifoDataLev = 0;
    USHORT16 usTxSize = pstParam->usCmdAddrSize + pstParam->usDataSize;
    USHORT16 usRxSize = pstParam->usDataSize;
    UINT32 usTxNumOnce = 0;
    UINT32 uiLoop = 0;
    UCHAR8 ucDummy = 0;
    USHORT16 usCmdAddrSize = pstParam->usCmdAddrSize;

    if (pstSelf->enState == I2C_STATE_READY)
    {
        if ((pstParam->pucData == NULL) || (pstParam->usDataSize == 0))
        {
            return  HV_FAILURE;
        }

        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }

        regTARVal.IC_10BITADDR_MASTER = pstSelf->enInitParam.enAddressingMode;
        regTARVal.IC_TAR = pstParam->usDevAddress;
        /* Normal TAR, No General Call and Start byte*/
        regTARVal.SPECIAL = 0;
        HV_W32_REG(CPU_SYS_I2C0_IC_TAR + pstSelf->uiBaseOffset, regTARVal);
        /*Clear Raw Interrupt status flag*/
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);
        /* Enable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 1);

        pstSelf->enState = I2C_STATE_BUSY_TXRX;
        pstSelf->enErrorCode = I2C_ERROR_NONE;

        while (usTxSize > 0)
        {
            usTxFifoSurpLev = I2C_FIFO_DEPTH - HV_R32(CPU_SYS_I2C0_TXFLR + uiBaseOffset);
            if (usTxFifoSurpLev < usTxSize)
            {
                usTxNumOnce = usTxFifoSurpLev;
            }
            else
            {
                usTxNumOnce = usTxSize;
            }

            for (uiLoop = 0; uiLoop < usTxNumOnce; uiLoop++)
            {
                if (usTxSize == 1)
                {
                    regDataCmdVal.STOP = 1;
                }
                if (usCmdAddrSize > 0)
                {
                    regDataCmdVal.DAT = (*pstParam->pucCmdAddr++);
                    HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset, regDataCmdVal);
                    usCmdAddrSize--;
                }
                else
                {
                    regDataCmdVal.CMD = 1;
                    regDataCmdVal.DAT = ucDummy;
                    HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset, regDataCmdVal);
                }
                usTxSize--;
            }

            uiRxFifoDataLev = HV_R32(CPU_SYS_I2C0_RXFLR + pstSelf->uiBaseOffset);
            for (uiLoop = 0; uiLoop < uiRxFifoDataLev; uiLoop++)
            {
                (*pstParam->pucData++) = (UCHAR8)HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
                usRxSize = usRxSize - 1;
            }
        }

        while (usRxSize > 0)
        {
            uiRxFifoDataLev = HV_R32(CPU_SYS_I2C0_RXFLR + pstSelf->uiBaseOffset);
            for (uiLoop = 0; uiLoop < uiRxFifoDataLev; uiLoop++)
            {
                (*pstParam->pucData++) = (UCHAR8)HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
                usRxSize = usRxSize - 1;
            }
        }
        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_STOP_DEF, HV_SET, uiTimeout) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }
        /*Clear Stop*/
        HV_R32( CPU_SYS_I2C0_IC_CLR_STOP_DET + uiBaseOffset);
        /* Enable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
        pstSelf->enState = I2C_STATE_READY;
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

/** Receive in master mode an amount of data in non-blocking mode with interrupt
 *  @param pstSelf i2c handler
 *  @param pstParam, target device address
 *  pointer to command data buffer
 *  command length
 *  pointer to data buffer to be receive
 *  amount of data to be receive
 *  @retval Status
*/
Status Hv_Cal_I2C_MasterIntReceive(HvCalI2c *pstSelf, I2cFuncParam *pstParam)
{
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UINT32 uiIntFlag = 0;
    rs_cpu_sys_i2c0_ic_tar regTARVal = {0};

    if (pstSelf->enState == I2C_STATE_READY)
    {
        if ((pstParam->pucData == NULL) || (pstParam->usDataSize == 0))
        {
            return  HV_FAILURE;
        }

        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }

        pstSelf->pucCmdAddr = pstParam->pucCmdAddr;
        pstSelf->usCmdAddrSize = pstParam->usCmdAddrSize;
        pstSelf->usTxferSize = pstParam->usDataSize;
        pstSelf->pucRxBuff = pstParam->pucData;
        pstSelf->usRxferSize = pstParam->usDataSize;
        pstSelf->usRxferCount = 0;

        regTARVal.IC_10BITADDR_MASTER = pstSelf->enInitParam.enAddressingMode;
        regTARVal.IC_TAR = pstParam->usDevAddress;
        /* Normal TAR, No General Call and Start byte*/
        regTARVal.SPECIAL = 0;
        HV_W32_REG(CPU_SYS_I2C0_IC_TAR + pstSelf->uiBaseOffset, regTARVal);
        /*Clear Interrupt status flag*/
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);

        uiIntFlag = I2C_FLAG_TX_OVER | I2C_FLAG_TX_EMPTY | I2C_FLAG_TX_ABRT | I2C_FLAG_STOP_DEF
                    | I2C_FLAG_MASTER_ON_HOLD | I2C_FLAG_STUCK_AT_LOW | I2C_FLAG_RX_FULL
                    | I2C_FLAG_RX_OVER | I2C_FLAG_RX_UNDER;
        I2C_IntSelectEn(pstSelf, uiIntFlag);

        pstSelf->enState = I2C_STATE_BUSY_TXRX;
        pstSelf->enErrorCode = I2C_ERROR_NONE;
        pstSelf->enTransCompleteFlag = I2C_TRANS_IN_PROCESS;
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 1);
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

Status Hv_Cal_I2C_MasterDmaReceive(HvCalI2c *self, USHORT16 devAddress, UCHAR8 *pCmdAddr, USHORT16 cmdAddrSize, UCHAR8* pRxData, USHORT16 dataSize) {

    UINT32 base_offset = self->uiBaseOffset;
    rs_cpu_sys_i2c0_ic_tar regTARVal = {0};

    UINT32 txTotalSize = cmdAddrSize;
    UINT32 rxTotalSize = dataSize;

    if (self->enState == I2C_STATE_READY)
    {
        if (I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }

        self->pucTxBuff = pCmdAddr;
        self->usTxferSize = txTotalSize;
        
        Hv_Cal_Dma_XferCallbackBond(self->hdmaTx, I2C_MasterDmaTransmitCpltCallback);
        Hv_Cal_Dma_XferCallbackBond(self->hdmaRx, I2C_MasterDmaReceiveCpltCallback);

        Hv_Cal_Dma_SetSrcFrameSize(self->hdmaTx, DMA_DATA_SIZE_8Bits);
        Hv_Cal_Dma_SetDstFrameSize(self->hdmaTx, DMA_DATA_SIZE_8Bits);
        Hv_Cal_Dma_SetBlockSize(self->hdmaTx, txTotalSize - 1);
        Hv_Cal_Dma_SetSrcAddr(self->hdmaTx, (UINT32)pCmdAddr);
        Hv_Cal_Dma_ChannelEn(self->hdmaTx);
        
        Hv_Cal_Dma_SetBlockSize(self->hdmaRx, rxTotalSize);
        Hv_Cal_Dma_SetDstAddr(self->hdmaRx, (UINT32)pRxData);
        Hv_Cal_Dma_ChannelEn(self->hdmaRx);

        regTARVal.IC_10BITADDR_MASTER = self->enInitParam.enAddressingMode;
        regTARVal.IC_TAR = devAddress;
        regTARVal.SPECIAL = 0;                                                /* Normal TAR, No General Call and Start byte*/
        HV_W32_REG(CPU_SYS_I2C0_IC_TAR + self->uiBaseOffset, regTARVal);

        I2C_ConfigDmaTxReg(self, I2C_DMA_TX_ENABLE, I2C_DMA_TDLR);
        I2C_ConfigDmaRxReg(self, I2C_DMA_RX_ENABLE, I2C_DMA_RDLR);
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + base_offset);                             /*Clear Raw Interrupt status flag*/
        self->enState = I2C_STATE_BUSY_TXRX;
        self->enErrorCode = I2C_ERROR_NONE;
        self->enTransCompleteFlag = I2C_TRANS_IN_PROCESS;
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, self->uiBaseOffset, ENABLE, 1);      /* Enable i2c*/
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

/** Transmits in slave mode an amount of data in blocking mode.
 *  @param pstSelf i2c handler
 *  @param pucData pointer to data buffer
 *  @param usSize amount of data to be sent
 *  @param uiTimeout uiTimeout duration
 *  @retval Status
 */
Status Hv_Cal_I2C_SlavePollingTransmit(HvCalI2c *pstSelf, UCHAR8 *pucData, USHORT16 usSize, UINT32 uiTimeout)
{

    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    rs_cpu_sys_i2c0_ic_data_cmd  regDataCmdVal = {0};
    HV_UNUSED(uiTimeout);

    if (pstSelf->enState == I2C_STATE_READY)
    {
        if ((pucData == NULL) || (usSize == 0))
        {
            return  HV_FAILURE;
        }
        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }
        /*Clear Raw Interrupt status flag*/
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);
        /* Enable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 1);
        pstSelf->enState = I2C_STATE_BUSY_TX;
        pstSelf->enErrorCode = I2C_ERROR_NONE;

        while (usSize > 0)
        {
            I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_RD_REQ, HV_SET, 0);
            if (I2C_GetFlag( pstSelf, I2C_FLAG_TX_ABRT) == 1 )
            {
                HV_R32(CPU_SYS_I2C0_IC_CLR_TX_ABRT + uiBaseOffset);
            }
            regDataCmdVal.DAT = (*pucData++);
            regDataCmdVal.CMD = 0;
            HV_W32_REG(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset, regDataCmdVal);
            usSize--;
            /* Clear read request flag*/
            HV_R32(CPU_SYS_I2C0_IC_CLR_RD_REQ + uiBaseOffset);
        }
        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }
        /* Disable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
        pstSelf->enState = I2C_STATE_READY;
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

/** Transmit in slave mode an amount of data in non-blocking mode with interrupt
 *  @param pstSelf i2c handler
 *  @param pucData pointer to data buffer
 *  @param usSize amount of data to be sent
 *  @retval Status
 */
Status Hv_Cal_I2C_SlaveIntTransmit(HvCalI2c *pstSelf, UCHAR8 *pucData, USHORT16 usSize)
{
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UINT32 uiIntFlag = 0;

    if ((pstSelf->enState == I2C_STATE_READY) || (pstSelf->enState == I2C_STATE_BUSY_SLAVE_RESTART))
    {
        if ((pucData == NULL) || (usSize == 0))
        {
            return  HV_FAILURE;
        }

        if (pstSelf->enState == I2C_STATE_READY)
        {
            if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
            {
                return HV_FAILURE;
            }
        }
        pstSelf->pucTxBuff = pucData;
        pstSelf->usTxferSize = usSize;
        pstSelf->usTxferCount = 0;
        /*Clear Interrupt status flag*/
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);

        uiIntFlag = I2C_FLAG_TX_OVER | I2C_FLAG_TX_ABRT | I2C_FLAG_RD_REQ | I2C_FLAG_STOP_DEF;
        I2C_IntSelectEn(pstSelf, uiIntFlag);

        pstSelf->enState = I2C_STATE_BUSY_TX;
        pstSelf->enErrorCode = I2C_ERROR_NONE;
        pstSelf->enTransCompleteFlag = I2C_TRANS_IN_PROCESS;
        /* Enable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 1);
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

/** Transmit in slave mode an amount of data in non-blocking mode with interrupt
 *  @param ucPort i2c port
 *  @param pucData pointer to data buffer
 *  @param usSize amount of data to be sent
 *  @retval Status
 */
Status Hv_Cal_I2C_SlaveTransmit(UCHAR8 ucPort, UCHAR8 *pucData, USHORT16 usSize)
{
    UINT32 uiValue = 0;
    if (ucPort >= I2C_PORT_MAX)
    {
        HV_LOGE("port not supported\n");
        return HV_FAILURE;
    }
    HvCalI2c *pstSelf = &s_stI2c[ucPort];

    if (pstSelf == NULL)
    {
        HV_LOGE("port not inited\n");
        return HV_FAILURE;
    }

    return Hv_Cal_I2C_SlaveIntTransmit(pstSelf, pucData, usSize);
}

/** Receive in slave mode an amount of data in blocking mode
 *  @param pstSelf i2c handler
 *  @param pucData pointer to data buffer
 *  @param usSize amount of data to be sent
 *  @param uiTimeout uiTimeout duration
 *  @retval Status
 */

Status Hv_Cal_I2C_SlaveDmaTransmit(HvCalI2c  *self, UCHAR8* pData, USHORT16 dataSize)
{
    UINT32 base_offset = self->uiBaseOffset;
    if (self->enState == I2C_STATE_READY)
    {
        if (I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }

        Hv_Cal_Dma_XferCallbackBond(self->hdmaTx, I2C_SlaveDmaTransmitCpltCallback);
        Hv_Cal_Dma_SetBlockSize(self->hdmaTx, dataSize);
        Hv_Cal_Dma_SetSrcAddr(self->hdmaTx, (UINT32)pData);
        Hv_Cal_Dma_ChannelEn(self->hdmaTx);

        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + base_offset);                                    /*Clear Raw Interrupt status flag*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, self->uiBaseOffset, ENABLE, 1);             /* Enable i2c*/

        I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_RD_REQ, HV_SET, 0);
        if (I2C_GetFlag(self, I2C_FLAG_TX_ABRT) == 1)
        {
            HV_R32(CPU_SYS_I2C0_IC_CLR_TX_ABRT + base_offset);
        }
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_DMA_CR, self->uiBaseOffset, TDMAE, 1);
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_DMA_TDLR, self->uiBaseOffset, DMATDL, 1);

        self->enState = I2C_STATE_BUSY_TX;
        self->enErrorCode = I2C_ERROR_NONE;
        self->enTransCompleteFlag = I2C_TRANS_IN_PROCESS;
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

Status Hv_Cal_I2C_SlavePollingReceive(HvCalI2c *pstSelf, UCHAR8 *pucData, USHORT16 usRxSize, UINT32 uiTimeout)
{
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UCHAR8 uiRxFifoDataLev = 0;
    UCHAR8 uiLoop = 0;
    rs_cpu_sys_i2c0_ic_slv_data_nack_only regRxFlr2Val = {0};

    if (pstSelf->enState == I2C_STATE_READY)
    {
        if ((pucData == NULL) || (usRxSize == 0))
        {
            return HV_FAILURE;
        }
        /* Normal ACK Mode */
        regRxFlr2Val.NACK = 0;
        HV_W32_REG(CPU_SYS_I2C0_IC_SLV_DATA_NACK_ONLY + uiBaseOffset, regRxFlr2Val);

        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }
        /*Clear Raw Interrupt status flag*/
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);
        /* Enable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 1);
        pstSelf->enState = I2C_STATE_BUSY_RX;
        pstSelf->enErrorCode = I2C_ERROR_NONE;

        while (usRxSize > 0)
        {
            uiRxFifoDataLev = HV_R32(CPU_SYS_I2C0_RXFLR + pstSelf->uiBaseOffset);
            for (uiLoop = 0; uiLoop < uiRxFifoDataLev; uiLoop++)
            {
                (*pucData++) = (UCHAR8)HV_R32(CPU_SYS_I2C0_IC_DATA_CMD + uiBaseOffset);
                usRxSize = usRxSize - 1;
            }
        }

        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_STOP_DEF, HV_SET, uiTimeout) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }
        HV_R32( CPU_SYS_I2C0_IC_CLR_STOP_DET + uiBaseOffset);
        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }
        /* Disable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 0);
        pstSelf->enState = I2C_STATE_READY;
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

/** enable Receive int in slave mode
 *  @param ucPort i2c port
 *  @retval Status
 */
Status Hv_Cal_I2C_SlaveIntReceiveEnable(UCHAR8 ucPort)
{
    if (ucPort >= I2C_PORT_MAX)
    {
        HV_LOGE("port not supported\n");
        return HV_FAILURE;
    }
    HvCalI2c *pstSelf = &s_stI2c[ucPort];
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UINT32 uiIntFlag = 0;

    if (pstSelf == NULL)
    {
        HV_LOGE("port not inited\n");
        return HV_FAILURE;
    }

    /*Clear Interrupt status flag*/
    HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);
    uiIntFlag = I2C_FLAG_STOP_DEF | I2C_FLAG_RX_FULL | I2C_FLAG_RX_OVER | I2C_FLAG_RX_UNDER | I2C_FLAG_RESTART_DEF;
    I2C_IntSelectEn(pstSelf, uiIntFlag);

    pstSelf->enErrorCode    = I2C_ERROR_NONE;
    pstSelf->enTransCompleteFlag = I2C_TRANS_IN_PROCESS;
    /* Enable i2c*/
    HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 1);
    return HV_SUCCESS;
}

/** Receive in slave mode an amount of data in non-blocking mode with interrupt
 *  @param pstSelf i2c handler
 *  @param pucData pointer to data buffer
 *  @param usSize amount of data to be sent
 *  @retval Status
 */
Status Hv_Cal_I2C_SlaveIntReceive(HvCalI2c *pstSelf, UCHAR8 *pucData)
 {
    UINT32 uiBaseOffset = pstSelf->uiBaseOffset;
    UINT32 uiIntFlag = 0;

    if (pstSelf->enState == I2C_STATE_READY)
    {
        if ((pucData == NULL))
        {
            return  HV_FAILURE;
        }

        /* Wait until BUSY flag is reset */
        if (I2C_WaitOnFlagUntilTimeout(pstSelf, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }

        pstSelf->pucRxBuff = pucData;
        pstSelf->usRxferCount = 0;

        /*Clear Interrupt status flag*/
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + uiBaseOffset);
        uiIntFlag = I2C_FLAG_STOP_DEF | I2C_FLAG_RX_FULL | I2C_FLAG_RX_OVER | I2C_FLAG_RX_UNDER | I2C_FLAG_RESTART_DEF;
        I2C_IntSelectEn(pstSelf, uiIntFlag);

        pstSelf->enState        = I2C_STATE_BUSY_RX;
        pstSelf->enErrorCode    = I2C_ERROR_NONE;
        pstSelf->enTransCompleteFlag = I2C_TRANS_IN_PROCESS;
        /* Enable i2c*/
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, pstSelf->uiBaseOffset, ENABLE, 1);
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

Status Hv_Cal_I2C_SlaveDmaReceive(HvCalI2c *self, UCHAR8* pData, USHORT16 dataSize)
{
    UINT32 base_offset = self->uiBaseOffset;
    if(self->enState == I2C_STATE_READY)
    {
        if(I2C_WaitOnFlagUntilTimeout(self, I2C_FLAG_BUSY, HV_RESET, I2C_TIMEOUT) != HV_SUCCESS)
        {
            return HV_FAILURE;
        }
        Hv_Cal_Dma_XferCallbackBond(self->hdmaRx, I2C_SlaveDmaReceiveCpltCallback);

        Hv_Cal_Dma_SetBlockSize(self->hdmaRx, dataSize);
        Hv_Cal_Dma_SetDstAddr(self->hdmaRx, (UINT32)pData);
        Hv_Cal_Dma_ChannelEn(self->hdmaRx);

        I2C_ConfigDmaRxReg(self, I2C_DMA_RX_ENABLE, I2C_DMA_RDLR);
        HV_R32(CPU_SYS_I2C0_IC_CLR_INT + base_offset);                             /*Clear Raw Interrupt status flag*/
        self->enState = I2C_STATE_BUSY_RX;
        self->enErrorCode = I2C_ERROR_NONE;
        self->enTransCompleteFlag = I2C_TRANS_IN_PROCESS;
        HV_W32_FIELD_EX(CPU_SYS_I2C0_IC_ENABLE, self->uiBaseOffset, ENABLE, 1);      /* Enable i2c*/
        return HV_SUCCESS;
    }
    else
    {
        return HV_FAILURE;
    }
}

/** Receive in slave mode an amount of data in non-blocking mode with interrupt
 *  @param pstSelf i2c handler
 *  @retval is or not
 */
BOOL Hv_Cal_I2C_TransferIsComplete(HvCalI2c *pstSelf)
{
    if (pstSelf->enTransCompleteFlag == I2C_TRANS_IN_PROCESS)
    {
        return HV_FALSE;
    }
    else
    if (pstSelf->enTransCompleteFlag == I2C_TRANS_END)
    {
        return HV_TRUE;
    }
    else
    {
        return HV_FALSE;
    }
}

USHORT16 Hv_Cal_I2C_GetRxDataCount(HvCalI2c *pstSelf)
{
    return pstSelf->usRxferCount;
}

VOID Hv_Cal_I2C_InitPin(I2cMode enMode, I2cPort enPort)
{
    UINT32 uiValue = 0;
    HV_R32_DECL_VAR();

    if (I2C_PORT_0 == enPort)
    {
        uiValue = HV_R32_FIELD(SYS_SH08_TOP_TX_CTRL_24, reg_i2cm0_scl_io_ctrl);
        if (I2C_MODE_MASTER == enMode)
        {
            uiValue &= ~0x40;
            uiValue |= 0x01;
            HV_W32_FIELD(SYS_SH08_TOP_TX_CTRL_24, reg_i2cm0_scl_io_ctrl, uiValue);
        }
        else
        {
            uiValue &= ~0x01;
            uiValue |= 0x40;
            HV_W32_FIELD(SYS_SH08_TOP_TX_CTRL_24, reg_i2cm0_scl_io_ctrl, uiValue);
        }
    }
    if (I2C_PORT_1 == enPort)
    {
        uiValue = HV_R32_FIELD(RX_SH08_TOP_RX_CTRL_38, reg_i2cs0_scl_io_ctrl);
        if (I2C_MODE_MASTER == enMode)
        {
            uiValue &= ~0x40;
            uiValue |= 0x01;
            HV_W32_FIELD(RX_SH08_TOP_RX_CTRL_38, reg_i2cs0_scl_io_ctrl, uiValue);
        }
        else
        {
            uiValue &= ~0x01;
            uiValue |= 0x40;
            HV_W32_FIELD(RX_SH08_TOP_RX_CTRL_38, reg_i2cs0_scl_io_ctrl, uiValue);
        }
    }
    return;
}

