/** * @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; }