/**
 * @file hv_cal_MI2c.c
 * @brief mi2c driver chip abstract layer file.
 * @details This file provides the following functions: \n
 *          (1) mi2c master tx/rx \n
 *          (2) mi2c savle tx/rx \n
 *          (3) mi2c init \n
 *
 * @author HiView SoC Software Team
 * @version 1.0.0
 * @date 2023-06-26
 * @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>      <td>init
 * </table>
 */
#include "Common/hv_comm_DataType.h"
#include "hv_comm_Define.h"
#include "hv_cal_MI2c.h"
#include "hv_chip_Config.h"
#include "hv_vos_Comm.h"
#include "hv_comm_Define.h"
#include "HV_PAGE_HT7315_8051_reg.h"


static UINT32 PM51_Reg_ReadMask(UINT32 ulRegAddr, UCHAR8 ucBitStartLow, UCHAR8 ucBitEndHigh)
{
    UINT32 ulRData;
    UINT32 ulMask = 0xFFFFFFFF;

    if ((ucBitStartLow > ucBitEndHigh)
        || (ucBitStartLow > 31)
        || (ucBitEndHigh > 31))
    {
        return 0xFFFFFFFF;
    }

    ulMask = ulMask << (31 - ucBitEndHigh);
    ulMask = ulMask >> (31 - ucBitEndHigh);
    ulMask = ulMask >> ucBitStartLow;
    ulMask = ulMask << ucBitStartLow;

    ulRData = HV_R32(ulRegAddr);
    ulRData &= ulMask;
    ulRData = ulRData >> ucBitStartLow;

    return ulRData;
}

static void PM51_Reg_WriteMask(UINT32 ulRegAddr, UCHAR8 ucBitStartLow, UCHAR8 ucBitEndHigh, UINT32 ulVal)
{
    UINT32 ulRData;
    UINT32 ulMask = 0xFFFFFFFF;

    if ((ucBitStartLow > ucBitEndHigh)
         || (ucBitStartLow > 31)
         || (ucBitEndHigh > 31))
    {
        return ;
    }
    ulMask = ulMask << (31 - ucBitEndHigh);
    ulMask = ulMask >> (31 - ucBitEndHigh);
    ulMask = ulMask >> ucBitStartLow;
    ulVal &= ulMask;

    ulVal = ulVal << ucBitStartLow;
    ulMask = ulMask << ucBitStartLow;
    ulMask = ~ulMask;

    ulRData = HV_R32(ulRegAddr);

    ulRData &= ulMask;
    ulRData |= ulVal;

    HV_W32(ulRegAddr, ulRData);

    return;
}

void Hv_Cal_MI2C_Init(void)
{
    PM51_Reg_WriteMask(HV_Standby__SH08_TOP_STBY__reg_mi2c_scl_func_sel_ADDR,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_scl_func_sel_BITSTART,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_scl_func_sel_BITEND, 0);
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__SH08_TOP_STBY__reg_mi2c_scl_io_ctrl_ADDR,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_scl_io_ctrl_BITSTART,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_scl_io_ctrl_BITEND, 0x13); /* [7]OD[6]IE[5]PD[4]PU[3]SMT[2]PIN2[1]PIN1[0]OE */
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__SH08_TOP_STBY__reg_mi2c_sda_func_sel_ADDR,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_sda_func_sel_BITSTART,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_sda_func_sel_BITEND, 0);
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__SH08_TOP_STBY__reg_mi2c_sda_io_ctrl_ADDR,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_sda_io_ctrl_BITSTART,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_sda_io_ctrl_BITEND, 0x51);
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__SH08_TOP_STBY__reg_mi2c_sda_in_in_sel_ADDR,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_sda_in_in_sel_BITSTART,
                      HV_Standby__SH08_TOP_STBY__reg_mi2c_sda_in_in_sel_BITEND, 0);
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_clk_en_ADDR,
                      HV_Standby__standby_i2c_reg__reg_clk_en_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_clk_en_BITEND, 1);      /*  i2c_clk_en */
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_speed_ADDR,
                      HV_Standby__standby_i2c_reg__reg_speed_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_speed_BITEND, I2C_SPEED);   /*  i2c_clk_speed_div */

    return;
}

UCHAR8 Hv_Cal_MI2C_E2PReadByte(UCHAR8 ucSlvID, USHORT16 usAddr, BOOL bSub2AddrEn)
{
    UINT32 ulTempData = 0;
    USHORT16 usTimeoutCount = 0;

    /* clk_en = 1,ucSlvID = (A2>>1) */
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_ADDR,
                      HV_Standby__standby_i2c_reg__reg_addr_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_addr_BITEND, usAddr);
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_slv_id_ADDR,
                      HV_Standby__standby_i2c_reg__reg_slv_id_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_slv_id_BITEND, ucSlvID);
    Hv_Vos_Delayus(100);
    if (bSub2AddrEn)
    {
        PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_length_ADDR,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITEND, 1);
    }
    else
    {
        PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_length_ADDR,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITEND, 0);
    }

    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_rw_sel_ADDR,
                      HV_Standby__standby_i2c_reg__reg_rw_sel_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_rw_sel_BITEND,1);       /* i2c = read,rw=1 */
    Hv_Vos_Delayus(100);
    /* PM51_Reg_WriteMask(REG_DATA_LENGTH,8,15,0);    i2c data lenth */
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_start_ADDR,
                      HV_Standby__standby_i2c_reg__reg_start_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_start_BITEND, 0);       /* i2c tranmit start */
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_start_ADDR,
                      HV_Standby__standby_i2c_reg__reg_start_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_start_BITEND, 1);       /* i2c tranmit start */
    Hv_Vos_Delayus(1000);
    /* Hv_PM51_Sys_DelayMs(1);  wait for eeprom operation */
    while (usTimeoutCount++<I2C_TIMEOUT_MAX)
    {
        if (((HV_R32(HV_Standby__standby_i2c_reg__reg_done_out_ADDR) & BIT_17)) == 0x0)
        {
            Hv_Vos_Delayus(1000);
        }
        else
        {
            break;
        }
    }

    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_done_out_ADDR,
                      HV_Standby__standby_i2c_reg__reg_done_out_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_done_out_BITEND, 0);
    Hv_Vos_Delayus(100);
    if (usTimeoutCount >= I2C_TIMEOUT_MAX)
    {
        HV_LOGI("I2C Read time out!\r\n");
    }
    Hv_Vos_Delayus(100);
    ulTempData = HV_R32(HV_Standby__standby_i2c_reg__reg_iic_rxdata_ADDR);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_read_done_ADDR,
                          HV_Standby__standby_i2c_reg__reg_read_done_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_read_done_BITEND, 1);

    Hv_Vos_Delayus(1000);
    return (ulTempData & 0xFF);
}

UCHAR8 Hv_Cal_MI2C_E2PReadBytes(UCHAR8 ucSlvID, USHORT16 usAddr, BOOL bSub2AddrEn, UCHAR8 ucSize, UCHAR8 *pucRevData)
{
    UINT32 ulTempData = 0;
    UINT32 uiFiFO = 0;
    UCHAR8 ucLast = 0;
    USHORT16 usTimeoutCount = 0;

    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_data_length_ADDR,
                        HV_Standby__standby_i2c_reg__reg_data_length_BITSTART,
                        HV_Standby__standby_i2c_reg__reg_data_length_BITEND, (ucSize-1));

    /* clk_en = 1,ucSlvID = (A2>>1) */
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_ADDR,
                      HV_Standby__standby_i2c_reg__reg_addr_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_addr_BITEND, usAddr);
    //Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_slv_id_ADDR,
                      HV_Standby__standby_i2c_reg__reg_slv_id_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_slv_id_BITEND, ucSlvID);
    //Hv_Vos_Delayus(100);
    if (bSub2AddrEn)
    {
        PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_length_ADDR,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITEND, 1);
    }
    else
    {
        PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_length_ADDR,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITEND, 0);
    }

    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_rw_sel_ADDR,
                      HV_Standby__standby_i2c_reg__reg_rw_sel_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_rw_sel_BITEND,1);       /* i2c = read,rw=1 */
    //Hv_Vos_Delayus(100);
    /* PM51_Reg_WriteMask(REG_DATA_LENGTH,8,15,0);    i2c data lenth */
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_start_ADDR,
                      HV_Standby__standby_i2c_reg__reg_start_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_start_BITEND, 0);       /* i2c tranmit start */
    //Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_start_ADDR,
                      HV_Standby__standby_i2c_reg__reg_start_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_start_BITEND, 1);       /* i2c tranmit start */
    Hv_Vos_Delayus(1000);



    for (usTimeoutCount = 0; usTimeoutCount < I2C_TIMEOUT_MAX; usTimeoutCount++)
    {
        if (ucSize > 4)
        {
            uiFiFO = HV_R32(HV_Standby__standby_i2c_reg__reg_fifo_empty_flag_ADDR);
            if ((uiFiFO & BIT_20) == 0)
            {
                Hv_Vos_Delayus(50);
                continue;
            }
            ucSize -= 4;
        }
        else
        {
            if (((HV_R32(HV_Standby__standby_i2c_reg__reg_done_out_ADDR) & BIT_17)) == 0x0)
            {
                Hv_Vos_Delayus(1000);
                continue;
            }
            ucLast = 1;
        }

        ulTempData = HV_R32(HV_Standby__standby_i2c_reg__reg_iic_rxdata_ADDR);
        PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_read_done_ADDR,
                          HV_Standby__standby_i2c_reg__reg_read_done_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_read_done_BITEND, 1);
        if (1 == ucLast)
        {
            while (ucSize--)
            {
                *pucRevData++ = (ulTempData>>((3-ucSize)*8)) & 0xff;
            }
            break;
        }
        else
        {
            *pucRevData++ = (ulTempData>>0) & 0xff;
            *pucRevData++ = (ulTempData>>8) & 0xff;
            *pucRevData++ = (ulTempData>>16) & 0xff;
            *pucRevData++ = (ulTempData>>24) & 0xff;
        }

    }

    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_done_out_ADDR,
                      HV_Standby__standby_i2c_reg__reg_done_out_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_done_out_BITEND, 0);
    if (usTimeoutCount >= I2C_TIMEOUT_MAX)
    {
        HV_LOGI("I2C Read time out!\r\n");
    }

    return 0;
}

void Hv_Cal_MI2C_E2PWriteByte(UCHAR8 ucSlvID,USHORT16 usAddr,BOOL bSub2AddrEn, UCHAR8 ucTransData)
{
    UINT32 ulTempData = 0;
    USHORT16 usTimeoutCount = 0;

    /* todo add i2c polling check if ack is given */
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_ADDR,
                      HV_Standby__standby_i2c_reg__reg_addr_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_addr_BITEND, usAddr);
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_slv_id_ADDR,
                      HV_Standby__standby_i2c_reg__reg_slv_id_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_slv_id_BITEND, ucSlvID);
    Hv_Vos_Delayus(100);
    if (bSub2AddrEn)
    {
        PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_length_ADDR,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITEND, 1);
    }
    else
    {
        PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_length_ADDR,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITEND, 0);
    }
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_rw_sel_ADDR,
                      HV_Standby__standby_i2c_reg__reg_rw_sel_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_rw_sel_BITEND, 0);       /* i2c = write,rw=0 */
    /* PM51_Reg_WriteMask(REG_DATA_LENGTH,8,15,0);    //i2c data lenth */
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_start_ADDR,
                      HV_Standby__standby_i2c_reg__reg_start_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_start_BITEND, 0);       /* i2c tranmit start */
    Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_start_ADDR,
                      HV_Standby__standby_i2c_reg__reg_start_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_start_BITEND, 1);       /* i2c tranmit start */

    ulTempData = ucTransData;
    Hv_Vos_Delayus(100);
    HV_W32(HV_Standby__standby_i2c_reg__reg_iic_txdata_ADDR, ulTempData);         /* write tx fifo */
    Hv_Vos_MSleep(1);                                        /*  wait for eeprom operation */

    while (usTimeoutCount++ < I2C_TIMEOUT_MAX)
    {
        if ((HV_R32(HV_Standby__standby_i2c_reg__reg_done_out_ADDR) & BIT_17) == 0x0)
        {
            Hv_Vos_Delayus(1000);
        }
        else
        {
            break;
        }
    }

    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_done_out_ADDR,
                      HV_Standby__standby_i2c_reg__reg_done_out_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_done_out_BITEND, 0);
    if (usTimeoutCount >= I2C_TIMEOUT_MAX)
    {
        HV_LOGI("I2C write time out!\r\n");
    }
    Hv_Vos_Delayus(1000);
    return;
}

void Hv_Cal_MI2C_E2PWriteBytes(UCHAR8 ucSlvID,USHORT16 usAddr,BOOL bSub2AddrEn, UCHAR8 ucSize, UCHAR8 *pucTransData)
{
    UINT32 ulTempData = 0;
    UINT32 uiFiFO = 0;
    USHORT16 usTimeoutCount = 0;

    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_data_length_ADDR,
                        HV_Standby__standby_i2c_reg__reg_data_length_BITSTART,
                        HV_Standby__standby_i2c_reg__reg_data_length_BITEND, (ucSize-1));

    /* todo add i2c polling check if ack is given */
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_ADDR,
                      HV_Standby__standby_i2c_reg__reg_addr_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_addr_BITEND, usAddr);
    //Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_slv_id_ADDR,
                      HV_Standby__standby_i2c_reg__reg_slv_id_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_slv_id_BITEND, ucSlvID);
    //Hv_Vos_Delayus(100);
    if (bSub2AddrEn)
    {
        PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_length_ADDR,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITEND, 1);
    }
    else
    {
        PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_addr_length_ADDR,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITSTART,
                          HV_Standby__standby_i2c_reg__reg_addr_length_BITEND, 0);
    }
    //Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_rw_sel_ADDR,
                      HV_Standby__standby_i2c_reg__reg_rw_sel_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_rw_sel_BITEND, 0);       /* i2c = write,rw=0 */
    /* PM51_Reg_WriteMask(REG_DATA_LENGTH,8,15,0);    //i2c data lenth */
    //Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_start_ADDR,
                      HV_Standby__standby_i2c_reg__reg_start_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_start_BITEND, 0);       /* i2c tranmit start */
    //Hv_Vos_Delayus(100);
    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_start_ADDR,
                      HV_Standby__standby_i2c_reg__reg_start_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_start_BITEND, 1);       /* i2c tranmit start */


    for (usTimeoutCount = 0; usTimeoutCount < I2C_TIMEOUT_MAX; usTimeoutCount++)
    {
        uiFiFO = HV_R32(HV_Standby__standby_i2c_reg__reg_fifo_empty_flag_ADDR);

        /* fifo full wait. */
        if ((uiFiFO & BIT_20) == BIT_20)
        {
            Hv_Vos_Delayus(100);
            continue;
        }
        /* fifo not empty. wait >4 clk. */
        if ((uiFiFO & BIT_19) == 0x0)
        {
            Hv_Vos_Delayus(50);
            continue;
        }

        ulTempData  = (*(pucTransData++) << 0);
        ulTempData |= (*(pucTransData++) << 8);
        ulTempData |= (*(pucTransData++) << 16);
        ulTempData |= (*(pucTransData++) << 24);
        HV_W32(HV_Standby__standby_i2c_reg__reg_iic_txdata_ADDR, ulTempData);

        if (ucSize >= 4)
        {
            ucSize -= 4;
            continue;
        }
        else
        {
            break;
        }
    }
    if (usTimeoutCount >= I2C_TIMEOUT_MAX)
    {
        HV_LOGI("I2C write time out!\r\n");
    }
    Hv_Vos_Delayus(100);                                       /*  wait for eeprom operation */

    for (usTimeoutCount = 0; usTimeoutCount <I2C_TIMEOUT_MAX; usTimeoutCount++)
    {
        if ((HV_R32(HV_Standby__standby_i2c_reg__reg_done_out_ADDR) & BIT_17) == 0x0)
        {
            Hv_Vos_Delayus(1000);
        }
        else
        {
            break;
        }
    }

    PM51_Reg_WriteMask(HV_Standby__standby_i2c_reg__reg_done_out_ADDR,
                      HV_Standby__standby_i2c_reg__reg_done_out_BITSTART,
                      HV_Standby__standby_i2c_reg__reg_done_out_BITEND, 0);
    if (usTimeoutCount >= I2C_TIMEOUT_MAX)
    {
        HV_LOGI("I2C write time out!\r\n");
    }
    Hv_Vos_Delayus(1000);
    return;
}
