/**
* @file hv_drv_Eeprom.c
* @brief eeprom driver layer file.
* @details This file provides the following functions: \n
* (1) eeprom write\n
* (2) eeprom read\n
* (3) eeprom protect \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:
*
* Author | Date | Change Description
* |
---|
HiView SoC Software Team | 2023-05-08 | init
* |
HiView SoC Software Team | 2023-06-27 | add simi2c、mi2c、wp control
* |
*/
#include "Common/hv_comm_DataType.h"
#include "hv_comm_Define.h"
#include "hv_cal_I2c.h"
#include "hv_drv_I2c.h"
#include "hv_chip_Config.h"
#include "hv_vos_Comm.h"
#include "hv_drv_Eeprom.h"
#include "hv_comm_Define.h"
#include "hv_drv_GpioSimI2c.h"
#include "hv_cal_MI2c.h"
#include "hv_drv_Gpio.h"
static HvCalI2c *apSelf[I2C_PORT_MAX] = {NULL, NULL};
typedef enum _EepromType
{
E2P_TYPE_1K_16PAGES_8BYTE = 0,
E2P_TYPE_2K_32PAGES_8BYTE,
E2P_TYPE_2K_16PAGES_16BYTE,
E2P_TYPE_4K_32PAGES_16BYTE,
E2P_TYPE_8K_64PAGES_16BYTE,
E2P_TYPE_16K_128PAGES_16BYTE,
E2P_TYPE_32K_128PAGES_32BYTE,
E2P_TYPE_64K_256PAGES_32BYTE,
} EepromType;
static void I2C_E2pType(UCHAR8 ucBus, USHORT16 *pAddrByteSize, USHORT16 *pBytesPerPage, USHORT16 *pTotalPageNum)
{
USHORT16 usAddrByteSize = 1;
USHORT16 usBytesPerPage = 8;
USHORT16 usTotalPageNum = 16;
EepromType enEepromType = E2P_TYPE_1K_16PAGES_8BYTE;
switch (ucBus)
{
#ifdef HV_BOARD_CONFIG_E2P_USE_I2CS0
case I2CS0:
{
enEepromType = HV_BOARD_CONFIG_E2P_TYPE_1;
break;
}
#endif
#ifdef HV_BOARD_CONFIG_E2P_USE_MI2C
case MI2C:
{
enEepromType = HV_BOARD_CONFIG_E2P_TYPE_2;
break;
}
#endif
#ifdef HV_BOARD_CONFIG_E2P_USE_SIMI2C0
case SIMI2C0:
{
enEepromType = HV_BOARD_CONFIG_E2P_TYPE_3;
break;
}
#endif
default:
{
break;
}
}
switch (enEepromType)
{
case E2P_TYPE_1K_16PAGES_8BYTE:
{
usAddrByteSize = 1;
usBytesPerPage = 8;
usTotalPageNum = 16;
break;
}
case E2P_TYPE_2K_32PAGES_8BYTE:
{
usAddrByteSize = 1;
usBytesPerPage = 8;
usTotalPageNum = 32;
break;
}
case E2P_TYPE_2K_16PAGES_16BYTE:
{
usAddrByteSize = 1;
usBytesPerPage = 16;
usTotalPageNum = 16;
break;
}
case E2P_TYPE_4K_32PAGES_16BYTE:
{
usAddrByteSize = 1;
usBytesPerPage = 16;
usTotalPageNum = 32;
break;
}
case E2P_TYPE_8K_64PAGES_16BYTE:
{
usAddrByteSize = 1;
usBytesPerPage = 16;
usTotalPageNum = 64;
break;
}
case E2P_TYPE_16K_128PAGES_16BYTE:
{
usAddrByteSize = 1;
usBytesPerPage = 16;
usTotalPageNum = 128;
break;
}
case E2P_TYPE_32K_128PAGES_32BYTE:
{
usAddrByteSize = 2;
usBytesPerPage = 32;
usTotalPageNum = 128;
break;
}
case E2P_TYPE_64K_256PAGES_32BYTE:
{
usAddrByteSize = 2;
usBytesPerPage = 32;
usTotalPageNum = 256;
break;
}
default:
{
HV_LOGI("No such e2p type .\n");
break;
}
}
*pAddrByteSize = usAddrByteSize;
*pBytesPerPage = usBytesPerPage;
*pTotalPageNum = usTotalPageNum;
return;
}
static Status _Eeprom_Write(UCHAR8 ucBus, USHORT16 usCmdAddr, USHORT16 usAddrByteSize, UCHAR8 *pucWtData, USHORT16 usWtDataSize)
{
int iLoop = 0;
UCHAR8 aucCmdAddr[2] = { 0 };
USHORT16 usDevAddress = 0;
BOOL bSub2AddrEn = HV_FALSE;
I2cFuncParam enI2cParam;
UCHAR8 ucDevAddr = 0;
UCHAR8 *pucCmdAddr = NULL;
aucCmdAddr[0] = usCmdAddr >> 8;
aucCmdAddr[1] = usCmdAddr & 0xff;
if (1 == usAddrByteSize)
{
pucCmdAddr = &aucCmdAddr[1];
}
else
{
pucCmdAddr = aucCmdAddr;
}
switch (ucBus)
{
#ifdef HV_BOARD_CONFIG_E2P_USE_I2CS0
case I2CS0:
{
enI2cParam.usDevAddress = HV_BOARD_CONFIG_E2P_ADDR_1;
enI2cParam.pucCmdAddr = pucCmdAddr;
enI2cParam.usCmdAddrSize = usAddrByteSize;
enI2cParam.pucData = pucWtData;
enI2cParam.usDataSize = usWtDataSize;
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_1, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_1?GPIO_LEVEL_LOW:GPIO_LEVEL_HIGH);
Hv_Drv_I2C_MasterPollingTransmit(apSelf[ucBus], &enI2cParam, 0);
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_1, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_1?GPIO_LEVEL_HIGH:GPIO_LEVEL_LOW);
break;
}
#endif
#ifdef HV_BOARD_CONFIG_E2P_USE_MI2C
case MI2C:
{
HV_LOGV("write: ucDevAddr %x, usCmdAddr %x\n", ucDevAddr, usCmdAddr);
ucDevAddr = HV_BOARD_CONFIG_E2P_ADDR_2;
if (usAddrByteSize == 1)
{
ucDevAddr |= (usCmdAddr >> 8) & 0x7;
usCmdAddr &= 0xff;
bSub2AddrEn = HV_FALSE;
}
else if (usAddrByteSize == 2)
{
bSub2AddrEn = HV_TRUE;
}
else
{
return HV_FAILURE;
}
HV_LOGV("write: ucDevAddr %x, usCmdAddr %x\n", ucDevAddr, usCmdAddr);
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_2, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_2?GPIO_LEVEL_LOW:GPIO_LEVEL_HIGH);
HV_LOGV("write: addr %x, addsize %d size %d\n", usCmdAddr, bSub2AddrEn, usWtDataSize);
#if 0
for (iLoop = 0; iLoop < usWtDataSize; iLoop++)
{
HV_LOGI("write:%d %x\n", iLoop,*(pucWtData+iLoop));
Hv_Cal_MI2C_E2PWriteByte(HV_BOARD_CONFIG_E2P_ADDR_2, usCmdAddr++, bSub2AddrEn, *(pucWtData + iLoop));
}
#else
Hv_Cal_MI2C_E2PWriteBytes(ucDevAddr, usCmdAddr, bSub2AddrEn, usWtDataSize, pucWtData);
for (iLoop = 0; iLoop < usWtDataSize; iLoop++)
{
HV_LOGV("write:%d %x\n", iLoop,*(pucWtData+iLoop));
}
#endif
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_2, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_2?GPIO_LEVEL_HIGH:GPIO_LEVEL_LOW);
break;
}
#endif
#ifdef HV_BOARD_CONFIG_E2P_USE_SIMI2C0
case SIMI2C0:
{
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_3, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_3?GPIO_LEVEL_LOW:GPIO_LEVEL_HIGH);
Hv_Drv_GpioSimI2c_SendData(SIMI2C0, HV_BOARD_CONFIG_E2P_ADDR_3, pucCmdAddr, usAddrByteSize,
pucWtData, usWtDataSize);
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_3, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_3?GPIO_LEVEL_HIGH:GPIO_LEVEL_LOW);
break;
}
#endif
default:
{
return HV_FAILURE;
}
}
return HV_SUCCESS;
}
static Status _Eeprom_Read(UCHAR8 ucBus, USHORT16 usCmdAddr, USHORT16 usAddrByteSize, UCHAR8 *pucRDData, USHORT16 usRDDataSize)
{
int iLoop = 0;
USHORT16 usDevAddress = 0;
UCHAR8 aucCmdAddr[2] = { 0 };
BOOL bSub2AddrEn = HV_FALSE;
I2cFuncParam enI2cParam;
UCHAR8 ucDevAddr = 0;
UCHAR8 *pucCmdAddr = NULL;
aucCmdAddr[0] = usCmdAddr >> 8;
aucCmdAddr[1] = usCmdAddr & 0xff;
if (1 == usAddrByteSize)
{
pucCmdAddr = &aucCmdAddr[1];
}
else
{
pucCmdAddr = aucCmdAddr;
}
switch (ucBus)
{
#ifdef HV_BOARD_CONFIG_E2P_USE_I2CS0
case I2CS0:
{
enI2cParam.usDevAddress = HV_BOARD_CONFIG_E2P_ADDR_1;
enI2cParam.pucCmdAddr = pucCmdAddr;
enI2cParam.usCmdAddrSize = usAddrByteSize;
enI2cParam.pucData = pucRDData;
enI2cParam.usDataSize = usRDDataSize;
return Hv_Drv_I2C_MasterPollingReceive(apSelf[ucBus], &enI2cParam, 0);
break;
}
#endif
#ifdef HV_BOARD_CONFIG_E2P_USE_MI2C
case MI2C:
{
HV_LOGV("write: ucDevAddr %x, usCmdAddr %x\n", ucDevAddr, usCmdAddr);
ucDevAddr = HV_BOARD_CONFIG_E2P_ADDR_2;
if (usAddrByteSize == 1)
{
ucDevAddr |= (usCmdAddr >> 8) & 0x7;
usCmdAddr &= 0xff;
bSub2AddrEn = HV_FALSE;
}
else if (usAddrByteSize == 2)
{
bSub2AddrEn = HV_TRUE;
}
else
{
return HV_FAILURE;
}
if (usRDDataSize < 4)
{
HV_LOGV("read: addr %x, addsize %d\n", usCmdAddr, bSub2AddrEn);
for (iLoop = 0; iLoop < usRDDataSize; iLoop++)
{
*(pucRDData + iLoop) = Hv_Cal_MI2C_E2PReadByte(HV_BOARD_CONFIG_E2P_ADDR_2, usCmdAddr++, bSub2AddrEn);
HV_LOGV("read: %d:%x\n", iLoop,*(pucRDData+iLoop));
}
}
else
{
HV_LOGV("write: ucDevAddr %x, usCmdAddr %x\n", ucDevAddr, usCmdAddr);
HV_LOGV("read: addr %x, addsize %d, size %d\n", usCmdAddr, bSub2AddrEn, usRDDataSize);
Hv_Cal_MI2C_E2PReadBytes(ucDevAddr, usCmdAddr, bSub2AddrEn, usRDDataSize, pucRDData);
for (iLoop = 0; iLoop < usRDDataSize; iLoop++)
{
HV_LOGV("read: %d:%x\n", iLoop,*(pucRDData+iLoop));
}
}
break;
}
#endif
#ifdef HV_BOARD_CONFIG_E2P_USE_SIMI2C0
case SIMI2C0:
{
return Hv_Drv_GpioSimI2c_RecvData(SIMI2C0, HV_BOARD_CONFIG_E2P_ADDR_3, pucCmdAddr, usAddrByteSize,
pucRDData, usRDDataSize);
}
#endif
default:
{
return HV_FAILURE;
}
}
return HV_SUCCESS;
}
/** Transmit an amount of data to Eeprom
* @param ucBus i2c bus
* @param usWtAddr address to write data
* @param pucWtData pointer to write data
* @param usWtDataSize size to write data.
* @retval Status
*/
Status Hv_Drv_Eeprom_Write(UCHAR8 ucBus, USHORT16 usWtAddr, UCHAR8 *pucWtData, USHORT16 usWtDataSize)
{
USHORT16 usPageNum = 0;
USHORT16 usStartDataSize = 0;
USHORT16 usEndDataSize = 0;
USHORT16 usAddrByteSize = 0;
USHORT16 usBytesPerPage = 0;
USHORT16 usTotalPageNum = 0;
USHORT16 usLoop = 0;
Status enStatus = HV_SUCCESS;
UCHAR8 *pData = NULL;
HvCalI2c *pstSelf = NULL;
pData = pucWtData;
I2C_E2pType(ucBus, &usAddrByteSize, &usBytesPerPage, &usTotalPageNum);
usStartDataSize = usBytesPerPage - (usWtAddr % usBytesPerPage);
if (usStartDataSize != usBytesPerPage)
{
if (usWtDataSize < usStartDataSize)
{
usStartDataSize = 0;
}
else
{
usWtDataSize -= usStartDataSize;
}
}
else
{
usStartDataSize = 0;
}
usPageNum = usWtDataSize / usBytesPerPage;
usEndDataSize = usWtDataSize % usBytesPerPage;
if (usStartDataSize != 0)
{
enStatus = _Eeprom_Write(ucBus, usWtAddr, usAddrByteSize, pData, usStartDataSize);
pData += usStartDataSize;
usWtAddr += usStartDataSize;
Hv_Vos_Delayus(5000);
}
for (usLoop = 0; usLoop < usPageNum; usLoop++)
{
enStatus = _Eeprom_Write(ucBus, usWtAddr, usAddrByteSize, pData, usBytesPerPage);
pData += usBytesPerPage;
usWtAddr += usBytesPerPage;
Hv_Vos_Delayus(5000);
}
if (usEndDataSize != 0)
{
enStatus = _Eeprom_Write(ucBus, usWtAddr, usAddrByteSize, pData, usEndDataSize);
Hv_Vos_Delayus(5000);
}
return enStatus;
}
/** receive an amount of data from eeprom
* @param ucBus i2c bus
* @param usRdAddr address to write data
* @param pucRdData pointer to write data
* @param usRdDataSize size to read data.
* @retval Status
*/
Status Hv_Drv_Eeprom_Read(UCHAR8 ucBus, USHORT16 usRdAddr, UCHAR8 *pucRdData, USHORT16 usRdDataSize)
{
USHORT16 usPageNum = 0;
USHORT16 usStartDataSize = 0;
USHORT16 usEndDataSize = 0;
USHORT16 usAddrByteSize = 0;
USHORT16 usBytesPerPage = 0;
USHORT16 usTotalPageNum = 0;
USHORT16 usLoop = 0;
Status enStatus = HV_SUCCESS;
UCHAR8 *pData = NULL;
HvCalI2c *pstSelf = NULL;
I2C_E2pType(ucBus, &usAddrByteSize, &usBytesPerPage, &usTotalPageNum);
pData = pucRdData;
usStartDataSize = usBytesPerPage - (usRdAddr % usBytesPerPage);
if (usStartDataSize != usBytesPerPage)
{
if (usRdDataSize < usStartDataSize)
{
usStartDataSize = 0;
}
else
{
usRdDataSize -= usStartDataSize;
}
}
else
{
usStartDataSize = 0;
}
usPageNum = usRdDataSize / usBytesPerPage;
usEndDataSize = usRdDataSize % usBytesPerPage;
if (usStartDataSize != 0)
{
enStatus = _Eeprom_Read(ucBus, usRdAddr, usAddrByteSize, pData, usStartDataSize);
pData += usStartDataSize;
usRdAddr += usStartDataSize;
Hv_Vos_Delayus(5000);
}
for (usLoop = 0; usLoop < usPageNum; usLoop++)
{
enStatus = _Eeprom_Read(ucBus, usRdAddr, usAddrByteSize, pData, usBytesPerPage);
pData += usBytesPerPage;
usRdAddr += usBytesPerPage;
Hv_Vos_Delayus(5000);
}
if (usEndDataSize != 0)
{
enStatus = _Eeprom_Read(ucBus, usRdAddr, usAddrByteSize, pData, usEndDataSize);
Hv_Vos_Delayus(5000);
}
return HV_SUCCESS;
}
/** init i2c for eeprom
* @retval Status
*/
Status Hv_Drv_Eeprom_Init(void)
{
I2cInitParam stInitParam;
GpioSimI2c stGpioSimi2c = {INVALID_PARAM_UHCAR8, INVALID_PARAM_UHCAR8};
#ifdef HV_BOARD_CONFIG_E2P_USE_I2CS0
stInitParam.enPort = I2C_PORT_1;
stInitParam.enMode = I2C_MODE_MASTER;
stInitParam.enSpeed = I2C_SPEED_100K;
stInitParam.enAddressingMode = I2C_ADDR_7BIT;
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_1, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_1?GPIO_LEVEL_HIGH:GPIO_LEVEL_LOW);
Hv_Drv_Gpio_SetDirection(HV_BOARD_CONFIG_E2P_WP_GPIO_1, GPIO_DIR_OUTPUT);
apSelf[I2CS0] = Hv_Drv_I2C_Init(&stInitParam);
#endif
#ifdef HV_BOARD_CONFIG_E2P_USE_I2CM0
stInitParam.enPort = I2C_PORT_0;
stInitParam.enMode = I2C_MODE_MASTER;
stInitParam.enSpeed = I2C_SPEED_100K;
stInitParam.enAddressingMode = I2C_ADDR_7BIT;
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_0, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_0?GPIO_LEVEL_HIGH:GPIO_LEVEL_LOW);
Hv_Drv_Gpio_SetDirection(HV_BOARD_CONFIG_E2P_WP_GPIO_0, GPIO_DIR_OUTPUT);
apSelf[I2CM0] = Hv_Drv_I2C_Init(&stInitParam);
#endif
#ifdef HV_BOARD_CONFIG_E2P_USE_SIMI2C0
stGpioSimi2c.ucSdaPin = SIMI2C_SDA;
stGpioSimi2c.ucSclPin = SIMI2C_SCL;
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_3, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_3?GPIO_LEVEL_HIGH:GPIO_LEVEL_LOW);
Hv_Drv_Gpio_SetDirection(HV_BOARD_CONFIG_E2P_WP_GPIO_3, GPIO_DIR_OUTPUT);
Hv_Drv_GpioSimI2c_Init(SIMI2C0, &stGpioSimi2c);
#endif
#ifdef HV_BOARD_CONFIG_E2P_USE_MI2C
Hv_Drv_Gpio_SetPinLevel(HV_BOARD_CONFIG_E2P_WP_GPIO_2, HV_BOARD_CONFIG_E2P_WP_PROTECT_LEVEL_2?GPIO_LEVEL_HIGH:GPIO_LEVEL_LOW);
Hv_Drv_Gpio_SetDirection(HV_BOARD_CONFIG_E2P_WP_GPIO_2, GPIO_DIR_OUTPUT);
Hv_Cal_MI2C_Init();
#endif
return HV_SUCCESS;
}