/** * @file hv_drv_Flash.c * @brief flash driver api layer file. * @details This file provides the following functions: \n * (1) flash write\n * (2) flash read\n * (3) flash init \n * * @author HiView SoC Software Team * @version 1.0.0 * @date 2023-05-11 * @copyright Copyright(c),2023-5, Hiview Software. All rights reserved. * @par History: * *
Author Date Change Description *
HiView SoC Software Team 2023-05-11 init *
*/ #include "Common/hv_comm_DataType.h" #include "hv_comm_Define.h" #include "hv_cal_Dma.h" #include "hv_cal_Qspi.h" #include "hv_drv_FlashDB.h" #include "hv_chip_Config.h" #include "hv_vos_Comm.h" #include "hv_vos_Cache.h" #include "hv_drv_Eeprom.h" #include "hv_drv_Flash.h" #include "hv_comm_FlashConfig.h" #define SECTOR_SIZE (4*1024) //4KB #define ERASE_TYPE FLASH_ERASE_SECTOR #define ERASE_TYPE_SIZE SECTOR_SIZE #define PAGE_WRITE 256 #define PAGE_READ 256 #define FLASH_BUSY_FLAG 0x01 #define FLASH_WAIT_INFINITE 0xFFFFFFFF #define FLASH_TIMEOUT 1000 #define FLASH_WAITBUSY_TIMEOUT 1000 #define FLASH_ERASE_MULTI_SECTOR_WAITBUSY_TIMEOUT 20000 #define FLASH_ERASECHIP_WAITBUSY_TIMEOUT 120000000 struct _FlashSelf { QspiSelf* pstQspi; /*!< Flash Init parameters. */ FlashInitParam InitParam; FlashAttribute flashAttr; UINT32 uiFlashID; }; static FlashSelf g_stFlash; static FlashSelf* g_pFlash = NULL; static UCHAR8 g_ucReadBuf[PAGE_READ] = {0}; static UCHAR8 g_ucSectorBuf[SECTOR_SIZE] = {0}; static UCHAR8 g_ucWriteBuf[PAGE_WRITE] = {0}; static UCHAR8 g_ucDmaUseFlag = HV_FALSE; static UCHAR8 g_ucIntUseFlag = HV_FALSE; static HV_VOS_SEMAPHORE_S *g_pstFlashSeamphone = NULL; static void Flash_OnlyRead(UINT32 uiReadAddr, UCHAR8* pucReadBuf, UINT32 uiLength); static Status Flash_Check(UINT32 uiWriteAddr, UCHAR8 *pucWriteBuf, UINT32 uiLength); static Status Flash_OnlyWrite(UINT32 uiWriteAddr, UCHAR8 *pucWriteBuf, UINT32 uiLength); static void Flash_CpltCallBack(FlashTransRW enTransType, void *pArg) { QspiSelf* pstQspi = (QspiSelf*)pArg; FlashSelf* pstFlash = (FlashSelf*)Hv_Cal_Qspi_GetFlashPoint(pstQspi); pstFlash->InitParam.FlashCpltCallback(enTransType, pstFlash); return; } static void Flash_SetCommonBaudRate(QspiInitParam* pstQspiInitParam, FlashInitParam *pstFlashInitParam) { if (pstFlashInitParam->RateMode == FLASH_STANDARD) { if (pstFlashInitParam->DataSize == FLASH_DATAWIDTH_8) { pstQspiInitParam->BaudRatePrescaler = QSPI_DIVRATIO_64; } else if (pstFlashInitParam->DataSize == FLASH_DATAWIDTH_16) { pstQspiInitParam->BaudRatePrescaler = QSPI_DIVRATIO_64; } else if (pstFlashInitParam->DataSize == FLASH_DATAWIDTH_32) { pstQspiInitParam->BaudRatePrescaler = QSPI_DIVRATIO_32; } } else if (pstFlashInitParam->RateMode == FLASH_DUAL) { pstQspiInitParam->BaudRatePrescaler = QSPI_DIVRATIO_256; } else if (pstFlashInitParam->RateMode == FLASH_QUAD) { pstQspiInitParam->BaudRatePrescaler = QSPI_DIVRATIO_256; } return; } static void Flash_SetDmaBaudRate(FlashSelf* pstFlash) { QspiSelf* pstQspi = pstFlash->pstQspi; FlashInitParam* InitParam = &pstFlash->InitParam; QspiDivideRatio qspiBaudDiv = QSPI_DIVRATIO_4; if (InitParam->RateMode == FLASH_STANDARD) { if (InitParam->DataSize == FLASH_DATAWIDTH_8) { qspiBaudDiv = QSPI_DIVRATIO_16; } else if (InitParam->DataSize == FLASH_DATAWIDTH_32) { qspiBaudDiv = QSPI_DIVRATIO_8; } } else if (InitParam->RateMode == FLASH_DUAL) { if (InitParam->DataSize == FLASH_DATAWIDTH_8) { qspiBaudDiv = QSPI_DIVRATIO_128; } else if (InitParam->DataSize == FLASH_DATAWIDTH_32) { qspiBaudDiv = QSPI_DIVRATIO_128; } } else if (InitParam->RateMode == FLASH_QUAD) { if (InitParam->DataSize == FLASH_DATAWIDTH_8) { qspiBaudDiv = QSPI_DIVRATIO_256; } else if (InitParam->DataSize == FLASH_DATAWIDTH_32) { qspiBaudDiv = QSPI_DIVRATIO_256; } } Hv_Cal_Qspi_SetBaudRate(pstQspi,qspiBaudDiv); return; } static void Flash_WriteEnable(FlashSelf* pstFlash) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 ucWtEnableCmd = pstFlash->flashAttr.FlashWriteEnCmd; UINT32 uiLoop = 0; Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Hv_Cal_Qspi_PollingWrite(pstQspi, &ucWtEnableCmd, 1, NULL, 0, FLASH_TIMEOUT); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL || pstFlash->InitParam.RateMode == FLASH_QUAD) { if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); } else if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_STAND, pstFlash->flashAttr.FlashInstruWidth, 0, 0); } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); } Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, &ucWtEnableCmd, 1, NULL, 0, FLASH_TIMEOUT); } for (uiLoop=0;uiLoop<2000;uiLoop++); return; } /************************************* Wait busy static API ********************************************/ static Status Flash_ReadBusyFlagStandard(FlashSelf * pstFlash, UINT64 timeout) { QspiSelf* pstQspi = pstFlash->pstQspi; UINT64 tickstart = 0; UCHAR8 aucRdState[2] = {0xff, 0xff}; UCHAR8 aucStateCmd[2] = {pstFlash->flashAttr.FlashReadStatusCmd, 0x00}; tickstart = Hv_Vos_GetTick(); while ((UCHAR8)((aucRdState[1] & FLASH_BUSY_FLAG)) != 0) { Hv_Cal_Qspi_PollingRead(pstQspi, aucStateCmd, 2, aucRdState, 0, FLASH_TIMEOUT); if ((timeout != FLASH_WAIT_INFINITE)) { if ((Hv_Vos_GetTick() - tickstart ) > timeout) { HV_LOGI("Flash busy until timeout.\n"); return HV_TIMEOUT; } } } return HV_SUCCESS; } static Status Flash_ReadBusyFlagMultiIo(FlashSelf * pstFlash, UINT64 timeout) { QspiSelf* pstQspi = pstFlash->pstQspi; UINT64 tickstart = 0; UCHAR8 ucRdState = 0xff; UCHAR8 ucStateCmd = pstFlash->flashAttr.FlashReadStatusCmd; tickstart = Hv_Vos_GetTick(); while ((UCHAR8)((ucRdState & FLASH_BUSY_FLAG)) != 0) { Hv_Cal_Qspi_MultiIoPollingRead(pstQspi, &ucStateCmd, 1, &ucRdState, 1, FLASH_TIMEOUT); if ((timeout != FLASH_WAIT_INFINITE)) { if ((Hv_Vos_GetTick() - tickstart ) > timeout) { HV_LOGI("Flash busy until timeout.\n"); return HV_TIMEOUT; } } } return HV_SUCCESS; } static void Flash_WaitBusy(FlashSelf* pstFlash, UINT64 Timeout) { QspiSelf* pstQspi = pstFlash->pstQspi; QspiState enRateMode = Hv_Cal_Qspi_GetRateMode(pstQspi); if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); Flash_ReadBusyFlagStandard(pstFlash, Timeout); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL || pstFlash->InitParam.RateMode == FLASH_QUAD) { if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_RX); Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); Hv_Cal_Qspi_SetReadNumber(pstQspi, 1); Flash_ReadBusyFlagMultiIo(pstFlash, Timeout); } else if ((pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) ||(pstFlash->InitParam.TransType == FLASH_ADDR_4LINE)) { Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); Flash_ReadBusyFlagStandard(pstFlash,Timeout); Hv_Cal_Qspi_SetRateMode(pstQspi,enRateMode); } } return; } /************************************* Wait busy static API end*******************************************/ /**************************************Read ID static function*******************************************/ static UINT32 Flash_ReadID_Standard(FlashSelf* pstFlash) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucReadID[4] = {0}; UINT32 uiFlashID = 0; if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_8) { UCHAR8 ucIdCmd = pstFlash->flashAttr.FlashReadIdStandardCmd; Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingRead(pstQspi, &ucIdCmd, 1, aucReadID, 3, FLASH_TIMEOUT); uiFlashID = ( (((UINT32)aucReadID[0]) << 16) | ((UINT32)aucReadID[1] << 8) | ((UINT32)aucReadID[2])); } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_32) { UCHAR8 aucIdCmd[4]={pstFlash->flashAttr.FlashReadIdStandardCmd,0x00,0x00,0x00}; Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_PollingRead(pstQspi, aucIdCmd, 4, aucReadID, 0, FLASH_TIMEOUT); uiFlashID = ( (((UINT32)aucReadID[1]) << 16) | ((UINT32)aucReadID[2] << 8) | ((UINT32)aucReadID[3])); } return uiFlashID; } static UINT32 Flash_ReadID_MutiIO(FlashSelf* pstFlash) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 ucIdCmd = pstFlash->flashAttr.FlashReadIdMultiIoCmd; UCHAR8 aucReadID[4] = {0}; UINT32 uiFlashID = 0; if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_RX); Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); Hv_Cal_Qspi_SetReadNumber(pstQspi, 3); Hv_Cal_Qspi_MultiIoPollingRead(pstQspi, &ucIdCmd, 1, aucReadID, 3, FLASH_TIMEOUT); uiFlashID = (((UINT32)aucReadID[0] << 16) | ((UINT32)aucReadID[1] << 8) | ((UINT32)aucReadID[2]) ); } else if ((pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) ||(pstFlash->InitParam.TransType == FLASH_ADDR_4LINE)) { QspiState enRateMode = Hv_Cal_Qspi_GetRateMode(pstQspi); Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); uiFlashID = Flash_ReadID_Standard(pstFlash); Hv_Cal_Qspi_SetRateMode(pstQspi,enRateMode); return uiFlashID; } return uiFlashID; } /**************************************Read ID static function end****************************************/ /**************************************Erase static function**********************************************/ static Status Flash_EraseStandard(FlashSelf* pstFlash, FlashEraseType enEraseType, UINT32 uiEraseAddr) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 eraseSector[5] = {0}; UCHAR8 eraseChip = 0; Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { if (enEraseType == FLASH_ERASE_SECTOR) { eraseSector[0] = pstFlash->flashAttr.FlashSectionEraseCmd; eraseSector[1] = (UCHAR8)((uiEraseAddr) >> 16); eraseSector[2] = (UCHAR8)((uiEraseAddr) >> 8); eraseSector[3] = (UCHAR8) uiEraseAddr; Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_PollingWrite(pstQspi, eraseSector, 4, NULL, 0, FLASH_TIMEOUT); Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); } else if (enEraseType == FLASH_ERASE_MULTI_SECTOR) { eraseSector[0] = pstFlash->flashAttr.FlashMultiSectionEraseCmd; eraseSector[1] = (UCHAR8)((uiEraseAddr) >> 16); eraseSector[2] = (UCHAR8)((uiEraseAddr) >> 8); eraseSector[3] = (UCHAR8) uiEraseAddr; Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_PollingWrite(pstQspi, eraseSector, 4, NULL, 0, FLASH_TIMEOUT); Flash_WaitBusy(pstFlash,FLASH_ERASE_MULTI_SECTOR_WAITBUSY_TIMEOUT); } else if (enEraseType == FLASH_ERASE_CHIP) { eraseChip = pstFlash->flashAttr.FlashChipEraseCmd; Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingWrite(pstQspi, &eraseChip, 1, NULL, 0, FLASH_TIMEOUT); Flash_WaitBusy(pstFlash,FLASH_ERASECHIP_WAITBUSY_TIMEOUT); } } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { if (enEraseType == FLASH_ERASE_SECTOR) { eraseSector[0] = pstFlash->flashAttr.FlashSectionEraseCmd_4ByteAddr; eraseSector[1] = (UCHAR8)((uiEraseAddr) >> 24); eraseSector[2] = (UCHAR8)((uiEraseAddr) >> 16); eraseSector[3] = (UCHAR8)((uiEraseAddr) >> 8); eraseSector[4] = (UCHAR8) uiEraseAddr; Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_SetBaudRate(pstQspi,QSPI_DIVRATIO_256); Hv_Cal_Qspi_PollingWrite(pstQspi, eraseSector, 5, NULL, 0, FLASH_TIMEOUT); Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); } else if (enEraseType == FLASH_ERASE_MULTI_SECTOR) { eraseSector[0] = pstFlash->flashAttr.FlashMultiSectionEraseCmd_4ByteAddr; eraseSector[1] = (UCHAR8)((uiEraseAddr) >> 24); eraseSector[2] = (UCHAR8)((uiEraseAddr) >> 16); eraseSector[3] = (UCHAR8)((uiEraseAddr) >> 8); eraseSector[4] = (UCHAR8) uiEraseAddr; Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingWrite(pstQspi, eraseSector, 5, NULL, 0, FLASH_TIMEOUT); Flash_WaitBusy(pstFlash,FLASH_ERASE_MULTI_SECTOR_WAITBUSY_TIMEOUT); } else if (enEraseType == FLASH_ERASE_CHIP) { eraseChip = pstFlash->flashAttr.FlashChipEraseCmd; Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingWrite(pstQspi, &eraseChip, 1, NULL, 0, FLASH_TIMEOUT); Flash_WaitBusy(pstFlash,FLASH_ERASECHIP_WAITBUSY_TIMEOUT); } } Hv_Vos_MSleep(pstFlash->flashAttr.FlashEraseCompltWait); return HV_SUCCESS; } static Status Flash_EraseMultiIo(FlashSelf* pstFlash, FlashEraseType enEraseType, UINT32 uiEraseAddr) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 eraseSector[5] = {0}; UCHAR8 eraseChip = 0; if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { if (enEraseType == FLASH_ERASE_SECTOR) { eraseSector[0] = pstFlash->flashAttr.FlashSectionEraseCmd; eraseSector[1] = (UCHAR8)((uiEraseAddr) >> 16); eraseSector[2] = (UCHAR8)((uiEraseAddr) >> 8); eraseSector[3] = (UCHAR8) uiEraseAddr; Hv_Cal_Qspi_SetBaudRate(pstQspi,QSPI_DIVRATIO_256); Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, eraseSector, 4, NULL, 0, FLASH_TIMEOUT); } else if (enEraseType == FLASH_ERASE_MULTI_SECTOR) { eraseSector[0] = pstFlash->flashAttr.FlashMultiSectionEraseCmd; eraseSector[1] = (UCHAR8)((uiEraseAddr) >> 16); eraseSector[2] = (UCHAR8)((uiEraseAddr) >> 8); eraseSector[3] = (UCHAR8) uiEraseAddr; Hv_Cal_Qspi_SetBaudRate(pstQspi,QSPI_DIVRATIO_256); Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, eraseSector, 4, NULL, 0, FLASH_TIMEOUT); } else if (enEraseType == FLASH_ERASE_CHIP) { eraseChip = pstFlash->flashAttr.FlashChipEraseCmd; Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, &eraseChip, 1, NULL, 0, FLASH_TIMEOUT); } } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { if (enEraseType == FLASH_ERASE_SECTOR) { eraseSector[0] = pstFlash->flashAttr.FlashSectionEraseCmd_4ByteAddr; eraseSector[1] = (UCHAR8)((uiEraseAddr) >> 24); eraseSector[2] = (UCHAR8)((uiEraseAddr) >> 16); eraseSector[3] = (UCHAR8)((uiEraseAddr) >> 8); eraseSector[4] = (UCHAR8) uiEraseAddr; Hv_Cal_Qspi_SetBaudRate(pstQspi,QSPI_DIVRATIO_256); Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, eraseSector, 5, NULL, 0, FLASH_TIMEOUT); } else if (enEraseType == FLASH_ERASE_MULTI_SECTOR) { eraseSector[0] = pstFlash->flashAttr.FlashMultiSectionEraseCmd_4ByteAddr; eraseSector[1] = (UCHAR8)((uiEraseAddr) >> 24); eraseSector[2] = (UCHAR8)((uiEraseAddr) >> 16); eraseSector[3] = (UCHAR8)((uiEraseAddr) >> 8); eraseSector[4] = (UCHAR8) uiEraseAddr; Hv_Cal_Qspi_SetBaudRate(pstQspi,QSPI_DIVRATIO_256); Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, eraseSector, 5, NULL, 0, FLASH_TIMEOUT); } else if (enEraseType == FLASH_ERASE_CHIP) { eraseChip = pstFlash->flashAttr.FlashChipEraseCmd; Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, &eraseChip, 1, NULL, 0, FLASH_TIMEOUT); } } if (enEraseType == FLASH_ERASE_SECTOR) { Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); } else if (enEraseType == FLASH_ERASE_MULTI_SECTOR) { Flash_WaitBusy(pstFlash,FLASH_ERASE_MULTI_SECTOR_WAITBUSY_TIMEOUT); } else if (enEraseType == FLASH_ERASE_CHIP) { Flash_WaitBusy(pstFlash,FLASH_ERASECHIP_WAITBUSY_TIMEOUT); } Hv_Vos_MSleep(pstFlash->flashAttr.FlashEraseCompltWait); } else if ((pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) ||(pstFlash->InitParam.TransType == FLASH_ADDR_4LINE)) { QspiRateMode enRateMode = Hv_Cal_Qspi_GetRateMode(pstQspi); Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Flash_EraseStandard(pstFlash,enEraseType,uiEraseAddr); Hv_Cal_Qspi_SetRateMode(pstQspi,enRateMode); } return HV_SUCCESS; } /**************************************Erase static function end********************************************/ /************************************************ Standard API *********************************************/ static Status Flash_SendStandard(FlashSelf* pstFlash, UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_8) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[0] = pstFlash->flashAttr.FlashProgStandardCmd; aucCmdAddr[1] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[2] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[3] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[0] = pstFlash->flashAttr.FlashProgStandardCmd_4ByteAddr; aucCmdAddr[1] = (uiWtAddr >> 24) & 0xff; aucCmdAddr[2] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[3] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[4] = uiWtAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { Hv_Cal_Qspi_PollingWrite(pstQspi, aucCmdAddr, 4, pucTxData, uiTxSize, FLASH_TIMEOUT); } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { Hv_Cal_Qspi_PollingWrite(pstQspi, aucCmdAddr, 5, pucTxData, uiTxSize, FLASH_TIMEOUT); } } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_16) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[0] = pstFlash->flashAttr.FlashProgStandardCmd; aucCmdAddr[1] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[2] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[3] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { HV_ASSERT(0); } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); Hv_Cal_Qspi_PollingWrite(pstQspi, aucCmdAddr, 4, pucTxData, uiTxSize, FLASH_TIMEOUT); } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_32) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[0] = pstFlash->flashAttr.FlashProgStandardCmd; aucCmdAddr[1] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[2] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[3] = uiWtAddr & 0xff; } else { HV_ASSERT(0); } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_PollingWrite(pstQspi, aucCmdAddr, 4, pucTxData, uiTxSize, FLASH_TIMEOUT); } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); return HV_SUCCESS; } static Status Flash_RecvStandard(FlashSelf* pstFlash, UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_8) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[0] = pstFlash->flashAttr.FlashReadStandardCmd; aucCmdAddr[1] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[2] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[3] = uiRdAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[0] = pstFlash->flashAttr.FlashReadStandardCmd_4ByteAddr; aucCmdAddr[1] = (uiRdAddr >> 24) & 0xff; aucCmdAddr[2] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[3] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[4] = uiRdAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { Hv_Cal_Qspi_PollingRead(pstQspi, aucCmdAddr, 4, pucRxData, uiRxSize, FLASH_TIMEOUT); } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { Hv_Cal_Qspi_PollingRead(pstQspi, aucCmdAddr, 5, pucRxData, uiRxSize, FLASH_TIMEOUT); } } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_16) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[0] = pstFlash->flashAttr.FlashReadStandardCmd; aucCmdAddr[1] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[2] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[3] = uiRdAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { HV_ASSERT(0); } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); Hv_Cal_Qspi_PollingRead(pstQspi, aucCmdAddr, 4, pucRxData, uiRxSize, FLASH_TIMEOUT); } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_32) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[0] = pstFlash->flashAttr.FlashReadStandardCmd; aucCmdAddr[1] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[2] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[3] = uiRdAddr & 0xff; } else { HV_ASSERT(0); } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_PollingRead(pstQspi, aucCmdAddr, 4, pucRxData, uiRxSize,FLASH_TIMEOUT); } return HV_SUCCESS; } static Status Flash_SendStandardInt(FlashSelf* pstFlash,UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Standard Int send just support 32bits DataWidth.\n"); HV_ASSERT(0); } aucCmdAddr[0] = pstFlash->flashAttr.FlashProgStandardCmd; aucCmdAddr[1] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[2] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[3] = uiWtAddr & 0xff; Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_IntWrite(pstQspi, aucCmdAddr, 4, pucTxData, uiTxSize); return HV_SUCCESS; } static Status Flash_RecvStandardInt(FlashSelf* pstFlash,UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Standard Int receive just support 32bits DataWidth.\n"); HV_ASSERT(0); } aucCmdAddr[0] = pstFlash->flashAttr.FlashReadStandardCmd; aucCmdAddr[1] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[2] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[3] = uiRdAddr & 0xff; Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_IntRead(pstQspi, aucCmdAddr, 4, pucRxData, uiRxSize); return HV_SUCCESS; } static Status Flash_SendStandardDma(FlashSelf* pstFlash,UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; FlashTxMem* TxDataDma = NULL; TxDataDma = (FlashTxMem*) (pucTxData - 20); if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_8) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { TxDataDma->cmdAddr[16] = pstFlash->flashAttr.FlashProgStandardCmd; TxDataDma->cmdAddr[17] = (uiWtAddr >> 16) & 0xff; TxDataDma->cmdAddr[18] = (uiWtAddr >> 8) & 0xff; TxDataDma->cmdAddr[19] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { TxDataDma->cmdAddr[15] = pstFlash->flashAttr.FlashProgStandardCmd; TxDataDma->cmdAddr[16] = (uiWtAddr >> 24) & 0xff; TxDataDma->cmdAddr[17] = (uiWtAddr >> 16) & 0xff; TxDataDma->cmdAddr[18] = (uiWtAddr >> 8) & 0xff; TxDataDma->cmdAddr[19] = uiWtAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Flash_SetDmaBaudRate(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[16], uiTxSize + 4); } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[15], uiTxSize + 5); } } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_32) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { TxDataDma->cmdAddr[16] = uiWtAddr & 0xff; TxDataDma->cmdAddr[17] = (uiWtAddr >> 8) & 0xff; TxDataDma->cmdAddr[18] = (uiWtAddr >> 16) & 0xff; TxDataDma->cmdAddr[19] = pstFlash->flashAttr.FlashProgStandardCmd; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { HV_ASSERT(0); } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Flash_SetDmaBaudRate(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[16], uiTxSize + 4); } return HV_SUCCESS; } static Status Flash_RecvStandardDma(FlashSelf* pstFlash, UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; static UCHAR8 g_aucCmdAddrBuf[1029]; if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_8) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { g_aucCmdAddrBuf[0] = pstFlash->flashAttr.FlashReadStandardCmd; g_aucCmdAddrBuf[1] = (uiRdAddr >> 16) & 0xff; g_aucCmdAddrBuf[2] = (uiRdAddr >> 8) & 0xff; g_aucCmdAddrBuf[3] = uiRdAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { g_aucCmdAddrBuf[0] = pstFlash->flashAttr.FlashReadStandardCmd; g_aucCmdAddrBuf[1] = (uiRdAddr >> 24) & 0xff; g_aucCmdAddrBuf[2] = (uiRdAddr >> 16) & 0xff; g_aucCmdAddrBuf[3] = (uiRdAddr >> 8) & 0xff; g_aucCmdAddrBuf[4] = uiRdAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_SetDmaBaudRate(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { Hv_Cal_Qspi_DmaRead(pstQspi, g_aucCmdAddrBuf, 4, pucRxData, uiRxSize); } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { Hv_Cal_Qspi_DmaRead(pstQspi, g_aucCmdAddrBuf, 5, pucRxData, uiRxSize); } } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_32) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { g_aucCmdAddrBuf[0] = uiRdAddr & 0xff; g_aucCmdAddrBuf[1] = (uiRdAddr >> 8) & 0xff; g_aucCmdAddrBuf[2] = (uiRdAddr >> 16) & 0xff; g_aucCmdAddrBuf[3] = pstFlash->flashAttr.FlashReadStandardCmd; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { HV_ASSERT(0); } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_SetDmaBaudRate(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_DmaRead(pstQspi, g_aucCmdAddrBuf, 4, pucRxData, uiRxSize); } return HV_SUCCESS; } /************************************************ Standard API end******************************************/ /*************************************************Dual API**************************************************/ static Status Flash_SendDual(FlashSelf* pstFlash, UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Dual Polling just support 32bits DataWidth.\n"); HV_ASSERT(0); } if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgDualCmd; aucCmdAddr[4] = 0; aucCmdAddr[5] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[6] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[7] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgDualCmd; aucCmdAddr[4] = (uiWtAddr >> 24) & 0xff; aucCmdAddr[5] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[6] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[7] = uiWtAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_STAND_ADDR_STAND, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, aucCmdAddr, 8, pucTxData, uiTxSize, FLASH_TIMEOUT); Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); return HV_SUCCESS; } static Status Flash_RecvDual(FlashSelf* pstFlash, UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Dual Polling just support 32bits DataWidth.\n"); HV_ASSERT(0); } if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadDualCmd; aucCmdAddr[4] = 0; aucCmdAddr[5] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[6] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[7] = uiRdAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadDualCmd; aucCmdAddr[4] = (uiRdAddr >> 24) & 0xff; aucCmdAddr[5] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[6] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[7] = uiRdAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_RX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_STAND,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleFastDual); } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleDual); } Hv_Cal_Qspi_SetReadNumber(pstQspi, uiRxSize); Hv_Cal_Qspi_MultiIoPollingRead(pstQspi, aucCmdAddr, 8, pucRxData, uiRxSize, FLASH_TIMEOUT); return HV_SUCCESS; } static Status Flash_SendDualInt(FlashSelf* pstFlash, UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Dual Int send just support 32bits DataWidth.\n"); HV_ASSERT(0); } if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgDualCmd; aucCmdAddr[4] = 0; aucCmdAddr[5] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[6] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[7] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgDualCmd; aucCmdAddr[4] = (uiWtAddr >> 24) & 0xff; aucCmdAddr[5] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[6] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[7] = uiWtAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_STAND,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } Hv_Cal_Qspi_IntWrite(pstQspi, aucCmdAddr, 8, pucTxData, uiTxSize); return HV_SUCCESS; } static Status Flash_RecvDualInt(FlashSelf* pstFlash, UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Dual Int receive just support 32bits DataWidth.\n"); HV_ASSERT(0); } if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadDualCmd; aucCmdAddr[4] = 0; aucCmdAddr[5] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[6] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[7] = uiRdAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadDualCmd; aucCmdAddr[4] = (uiRdAddr >> 24) & 0xff; aucCmdAddr[5] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[6] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[7] = uiRdAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_RX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_STAND_ADDR_STAND, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleFastDual); } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleDual); } Hv_Cal_Qspi_SetReadNumber(pstQspi, uiRxSize); Hv_Cal_Qspi_IntRead(pstQspi, aucCmdAddr, 8, pucRxData, uiRxSize); return HV_SUCCESS; } static Status Flash_SendDualDma(FlashSelf* pstFlash, UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; FlashTxMem* TxDataDma = NULL; UINT32 uiWtCmdTemp = 0; UINT64 wtAddrTemp = 0; UINT32 uiLoop = 0; TxDataDma = (FlashTxMem*) (pucTxData - 20); if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_8) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { TxDataDma->cmdAddr[16] = pstFlash->flashAttr.FlashProgDualCmd; TxDataDma->cmdAddr[17] = (uiWtAddr >> 16) & 0xff; TxDataDma->cmdAddr[18] = (uiWtAddr >> 8) & 0xff; TxDataDma->cmdAddr[19] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { for (uiLoop = 0;uiLoop < 24;uiLoop++ ) { if (uiLoop < 8) { uiWtCmdTemp |= ((UINT32)(pstFlash->flashAttr.FlashProgDualCmd & (1 << uiLoop))) << uiLoop; uiWtCmdTemp |= ((UINT32)((1 << uiLoop))) << (uiLoop+1); } wtAddrTemp |= ((UINT64)(uiWtAddr & (1 << uiLoop))) << uiLoop; wtAddrTemp |= ((UINT64)((1 << uiLoop))) << (uiLoop+1); } TxDataDma->cmdAddr[12] = (uiWtCmdTemp >> 8) & 0xff; TxDataDma->cmdAddr[13] = uiWtCmdTemp & 0xff; TxDataDma->cmdAddr[14] = (wtAddrTemp >> 40) & 0xff ; TxDataDma->cmdAddr[15] = (wtAddrTemp >> 32) & 0xff; TxDataDma->cmdAddr[16] = (wtAddrTemp >> 24) & 0xff; TxDataDma->cmdAddr[17] = (wtAddrTemp >> 16) & 0xff; TxDataDma->cmdAddr[18] = (wtAddrTemp >> 8) & 0xff; TxDataDma->cmdAddr[19] = wtAddrTemp & 0xff; } } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { TxDataDma->cmdAddr[15] = pstFlash->flashAttr.FlashProgDualCmd; TxDataDma->cmdAddr[16] = (uiWtAddr >> 24) & 0xff; TxDataDma->cmdAddr[17] = (uiWtAddr >> 16) & 0xff; TxDataDma->cmdAddr[18] = (uiWtAddr >> 8) & 0xff; TxDataDma->cmdAddr[19] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { HV_ASSERT(1); } } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Flash_SetDmaBaudRate(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[12], uiTxSize + 8); } } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[16], uiTxSize + 4); } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[15], uiTxSize + 5); } } } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_32) { TxDataDma->cmdAddr[12] = pstFlash->flashAttr.FlashProgDualCmd; TxDataDma->cmdAddr[13] = 0x00; TxDataDma->cmdAddr[14] = 0x00; TxDataDma->cmdAddr[15] = 0x00; TxDataDma->cmdAddr[16] = uiWtAddr & 0xff; TxDataDma->cmdAddr[17] = (uiWtAddr >> 8) & 0xff; TxDataDma->cmdAddr[18] = (uiWtAddr >> 16) & 0xff; if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { TxDataDma->cmdAddr[19] = 0; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { TxDataDma->cmdAddr[19] = (uiWtAddr >> 24) & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Flash_SetDmaBaudRate(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_STAND_ADDR_STAND, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[12], uiTxSize + 8); } return HV_SUCCESS; } static Status Flash_RecvDualDma(FlashSelf* pstFlash, UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; aucCmdAddr[0] = pstFlash->flashAttr.FlashReadDualCmd; if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[1] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[2] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[3] = uiRdAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[1] = (uiRdAddr >> 24) & 0xff; aucCmdAddr[2] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[3] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[4] = uiRdAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); /* Here can set different BaudDiv for different flash type, such as GD25F128 can support up to 166MHz dual fast read mode */ if (pstFlash->InitParam.FlashModel == FLASH_GD25) { Hv_Cal_Qspi_SetBaudRate(pstFlash->pstQspi, QSPI_DIVRATIO_2); } else { Flash_SetDmaBaudRate(pstFlash); } if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_8) { Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); }else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_32) { Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); } Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_RX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_STAND,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleFastDual); } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleDual); } Hv_Cal_Qspi_SetReadNumber(pstQspi, uiRxSize); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { Hv_Cal_Qspi_DmaRead(pstQspi, aucCmdAddr, 4, pucRxData, uiRxSize); } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { Hv_Cal_Qspi_DmaRead(pstQspi, aucCmdAddr, 5, pucRxData, uiRxSize); } return HV_SUCCESS; } /*************************************************Dual API end***************************************/ /**********************************************Quad API***********************************************/ static Status Flash_SendQuad(FlashSelf* pstFlash, UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Quad Polling just support 32bits DataWidth.\n"); HV_ASSERT(0); } if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgQuadCmd; } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProg4xIoCmd; } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgQpiCmd; } aucCmdAddr[4] = 0x00; aucCmdAddr[5] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[6] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[7] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgQuadCmd_4ByteAddr; } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProg4xIoCmd_4ByteAddr; } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgQpiCmd_4ByteAddr; } aucCmdAddr[4] = (uiWtAddr >> 24) & 0xff; aucCmdAddr[5] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[6] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[7] = uiWtAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_STAND_ADDR_STAND, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_STAND_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, aucCmdAddr, 8, pucTxData, uiTxSize, FLASH_TIMEOUT); Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); return HV_SUCCESS; } static Status Flash_RecvQuad(FlashSelf* pstFlash, UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Quad Polling just support 32bits DataWidth.\n"); HV_ASSERT(0); } if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadQuadCmd; } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashRead4xIoCmd; } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadQpiCmd; } aucCmdAddr[4] = 0x00; aucCmdAddr[5] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[6] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[7] = uiRdAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadQuadCmd_4ByteAddr; } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashRead4xIoCmd_4ByteAddr; } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadQpiCmd_4ByteAddr; } aucCmdAddr[4] = (uiRdAddr >> 24) & 0xff; aucCmdAddr[5] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[6] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[7] = uiRdAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_RX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_STAND,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleFastQuad); } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleQpi); } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_MULTI,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycle4xIo); } Hv_Cal_Qspi_SetReadNumber(pstQspi, uiRxSize); Hv_Cal_Qspi_MultiIoPollingRead(pstQspi, aucCmdAddr, 8, pucRxData, uiRxSize, FLASH_TIMEOUT); return HV_SUCCESS; } static Status Flash_SendQuadInt(FlashSelf* pstFlash, UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Quad Int send just support 32bits DataWidth.\n"); HV_ASSERT(0); } if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgQuadCmd; } else { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgQpiCmd; } aucCmdAddr[4] = 0x00; aucCmdAddr[5] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[6] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[7] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgQuadCmd; } else { aucCmdAddr[3] = pstFlash->flashAttr.FlashProgQpiCmd; } aucCmdAddr[4] = (uiWtAddr >> 24) & 0xff; aucCmdAddr[5] = (uiWtAddr >> 16) & 0xff; aucCmdAddr[6] = (uiWtAddr >> 8) & 0xff; aucCmdAddr[7] = uiWtAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_STAND_ADDR_STAND, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } Hv_Cal_Qspi_IntWrite(pstQspi, aucCmdAddr, 8, pucTxData, uiTxSize); return HV_SUCCESS; } static Status Flash_RecvQuadInt(FlashSelf* pstFlash, UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.DataSize != FLASH_DATAWIDTH_32) { HV_LOGI("Quad Int receive just support 32bits DataWidth.\n"); HV_ASSERT(0); } if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadQuadCmd; } else { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadQpiCmd; } aucCmdAddr[4] = 0x00; aucCmdAddr[5] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[6] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[7] = uiRdAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadQuadCmd; } else { aucCmdAddr[3] = pstFlash->flashAttr.FlashReadQpiCmd; } aucCmdAddr[4] = (uiRdAddr >> 24) & 0xff; aucCmdAddr[5] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[6] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[7] = uiRdAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_RX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_STAND_ADDR_STAND, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleFastQuad); } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleQpi); } Hv_Cal_Qspi_SetReadNumber(pstQspi, uiRxSize); Hv_Cal_Qspi_IntRead(pstQspi, aucCmdAddr, 8, pucRxData, uiRxSize); return HV_SUCCESS; } static Status Flash_SendQuadDma(FlashSelf* pstFlash, UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; FlashTxMem* TxDataDma = NULL; UINT32 uiWtCmdTemp = 0; UINT64 wtAddrTempHigh = 0; UINT64 wtAddrTempLow = 0; UINT32 uiLoop = 0; TxDataDma = (FlashTxMem*) (pucTxData - 20); if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_8) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { TxDataDma->cmdAddr[16] = pstFlash->flashAttr.FlashProgQpiCmd; TxDataDma->cmdAddr[17] = (uiWtAddr >> 16) & 0xff; TxDataDma->cmdAddr[18] = (uiWtAddr >> 8) & 0xff; TxDataDma->cmdAddr[19] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { for (uiLoop = 0;uiLoop < 16;uiLoop++) { wtAddrTempLow |= ((UINT64)(uiWtAddr & (1 << uiLoop))) << 3 * uiLoop; wtAddrTempLow |= ((UINT64)((0xe << uiLoop))) << 3 * uiLoop; if (uiLoop < 8) { uiWtCmdTemp |= ((UINT32)(pstFlash->flashAttr.FlashProgQuadCmd & (1 << uiLoop))) << 3 * uiLoop; uiWtCmdTemp |= ((UINT32)((0xe << uiLoop))) << 3 * uiLoop; wtAddrTempHigh |= ((UINT64)(((uiWtAddr >> 16) & (1 << uiLoop)))) << 3 * uiLoop; wtAddrTempHigh |= ((UINT64)((0xe << uiLoop))) << 3 * uiLoop; } } TxDataDma->cmdAddr[4] = (uiWtCmdTemp >> 24) & 0xff; TxDataDma->cmdAddr[5] = (uiWtCmdTemp >> 16) & 0xff; TxDataDma->cmdAddr[6] = (uiWtCmdTemp >> 8) & 0xff; TxDataDma->cmdAddr[7] = uiWtCmdTemp & 0xff; TxDataDma->cmdAddr[8] = (wtAddrTempHigh >> 24) & 0xff; TxDataDma->cmdAddr[9] = (wtAddrTempHigh >> 16) & 0xff; TxDataDma->cmdAddr[10] = (wtAddrTempHigh >> 8) & 0xff; TxDataDma->cmdAddr[11] = wtAddrTempHigh & 0xff; TxDataDma->cmdAddr[12] = (wtAddrTempLow >> 56) & 0xff; TxDataDma->cmdAddr[13] = (wtAddrTempLow >> 48) & 0xff; TxDataDma->cmdAddr[14] = (wtAddrTempLow >> 40) & 0xff; TxDataDma->cmdAddr[15] = (wtAddrTempLow >> 32) & 0xff; TxDataDma->cmdAddr[16] = (wtAddrTempLow >> 24) & 0xff; TxDataDma->cmdAddr[17] = (wtAddrTempLow >> 16) & 0xff; TxDataDma->cmdAddr[18] = (wtAddrTempLow >> 8) & 0xff; TxDataDma->cmdAddr[19] = wtAddrTempLow & 0xff; } } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { TxDataDma->cmdAddr[15] = pstFlash->flashAttr.FlashProgQpiCmd; TxDataDma->cmdAddr[16] = (uiWtAddr >> 24) & 0xff; TxDataDma->cmdAddr[17] = (uiWtAddr >> 16) & 0xff; TxDataDma->cmdAddr[18] = (uiWtAddr >> 8) & 0xff; TxDataDma->cmdAddr[19] = uiWtAddr & 0xff; } else if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { UINT32 uiWtCmdTemp = 0; UINT64 wtAddrTempHigh = 0; UINT64 wtAddrTempLow = 0; UINT32 uiLoop = 0; for (uiLoop = 0;uiLoop < 16;uiLoop++) { wtAddrTempLow |= ((UINT64)(uiWtAddr & (1 << uiLoop))) << 3 * uiLoop; wtAddrTempLow |= ((UINT64)((0xe << uiLoop))) << 3 * uiLoop; if (uiLoop < 8) { uiWtCmdTemp |= ((UINT32)(pstFlash->flashAttr.FlashProgQuadCmd & (1 << uiLoop))) << 3 * uiLoop; uiWtCmdTemp |= ((UINT32)((0xe << uiLoop))) << 3 * uiLoop; wtAddrTempHigh |= ((UINT64)(((uiWtAddr >> 16) & (1 << uiLoop)))) << 3 * uiLoop; wtAddrTempHigh |= ((UINT64)((0xe << uiLoop))) << 3 * uiLoop; } } TxDataDma->cmdAddr[0] = (uiWtCmdTemp >> 24) & 0xff; TxDataDma->cmdAddr[1] = (uiWtCmdTemp >> 16) & 0xff; TxDataDma->cmdAddr[2] = (uiWtCmdTemp >> 8) & 0xff; TxDataDma->cmdAddr[3] = uiWtCmdTemp & 0xff; TxDataDma->cmdAddr[4] = (wtAddrTempLow >> 56) & 0xff; TxDataDma->cmdAddr[5] = (wtAddrTempLow >> 48) & 0xff; TxDataDma->cmdAddr[6] = (wtAddrTempLow >> 40) & 0xff; TxDataDma->cmdAddr[7] = (wtAddrTempLow >> 32) & 0xff; TxDataDma->cmdAddr[8] = (wtAddrTempHigh >> 24) & 0xff; TxDataDma->cmdAddr[9] = (wtAddrTempHigh >> 16) & 0xff; TxDataDma->cmdAddr[10] = (wtAddrTempHigh >> 8) & 0xff; TxDataDma->cmdAddr[11] = wtAddrTempHigh & 0xff; TxDataDma->cmdAddr[12] = (wtAddrTempLow >> 56) & 0xff; TxDataDma->cmdAddr[13] = (wtAddrTempLow >> 48) & 0xff; TxDataDma->cmdAddr[14] = (wtAddrTempLow >> 40) & 0xff; TxDataDma->cmdAddr[15] = (wtAddrTempLow >> 32) & 0xff; TxDataDma->cmdAddr[16] = (wtAddrTempLow >> 24) & 0xff; TxDataDma->cmdAddr[17] = (wtAddrTempLow >> 16) & 0xff; TxDataDma->cmdAddr[18] = (wtAddrTempLow >> 8) & 0xff; TxDataDma->cmdAddr[19] = wtAddrTempLow & 0xff; } } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Flash_SetDmaBaudRate(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[4], uiTxSize + 16); } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[0], uiTxSize + 20); } } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24){ Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[16], uiTxSize + 4); } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[15], uiTxSize + 5); } } } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_32) { if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { TxDataDma->cmdAddr[12] = pstFlash->flashAttr.FlashProgQuadCmd; } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { TxDataDma->cmdAddr[12] = pstFlash->flashAttr.FlashProgQpiCmd; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { TxDataDma->cmdAddr[12] = pstFlash->flashAttr.FlashProgQpiCmd_4ByteAddr; } } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { TxDataDma->cmdAddr[12] = pstFlash->flashAttr.FlashProg4xIoCmd; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { TxDataDma->cmdAddr[12] = pstFlash->flashAttr.FlashProg4xIoCmd_4ByteAddr; } } TxDataDma->cmdAddr[13] = 0x00; TxDataDma->cmdAddr[14] = 0x00; TxDataDma->cmdAddr[15] = 0x00; TxDataDma->cmdAddr[16] = uiWtAddr & 0xff; TxDataDma->cmdAddr[17] = (uiWtAddr >> 8) & 0xff; TxDataDma->cmdAddr[18] = (uiWtAddr >> 16) & 0xff; if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { TxDataDma->cmdAddr[19] = 0x00; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { TxDataDma->cmdAddr[19] = (uiWtAddr >> 24) & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_WriteEnable(pstFlash); Flash_SetDmaBaudRate(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_STAND_ADDR_STAND, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi,QSPI_INSTRU_STAND_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, 0); } Hv_Cal_Qspi_DmaWrite(pstQspi, &TxDataDma->cmdAddr[12], uiTxSize + 8); } return HV_SUCCESS; } static Status Flash_RecvQuadDma(FlashSelf* pstFlash, UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { QspiSelf* pstQspi = pstFlash->pstQspi; UINT32 uiLoop = 0; UCHAR8 aucCmdAddr[8] = {0}; if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { aucCmdAddr[0] = pstFlash->flashAttr.FlashReadQuadCmd; } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[0] = pstFlash->flashAttr.FlashReadQpiCmd; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[0] = pstFlash->flashAttr.FlashReadQpiCmd_4ByteAddr; } } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[0] = pstFlash->flashAttr.FlashRead4xIoCmd; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[0] = pstFlash->flashAttr.FlashRead4xIoCmd_4ByteAddr; } } if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { aucCmdAddr[1] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[2] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[3] = uiRdAddr & 0xff; } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { aucCmdAddr[1] = (uiRdAddr >> 24) & 0xff; aucCmdAddr[2] = (uiRdAddr >> 16) & 0xff; aucCmdAddr[3] = (uiRdAddr >> 8) & 0xff; aucCmdAddr[4] = uiRdAddr & 0xff; } Flash_WaitBusy(pstFlash,FLASH_WAITBUSY_TIMEOUT); Flash_SetDmaBaudRate(pstFlash); if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_8) { Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); } else if (pstFlash->InitParam.DataSize == FLASH_DATAWIDTH_32) { Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); } Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_RX); if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_STAND,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleFastQuad); } else if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycleQpi); } else if (pstFlash->InitParam.TransType == FLASH_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_MULTI,pstFlash->flashAttr.FlashInstruWidth, pstFlash->InitParam.AddrWidth, pstFlash->flashAttr.FlashCycle4xIo); } Hv_Cal_Qspi_SetReadNumber(pstQspi, uiRxSize); if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_24) { Hv_Cal_Qspi_DmaRead(pstQspi, aucCmdAddr, 4, pucRxData, uiRxSize); } else if (pstFlash->InitParam.AddrWidth == FLASH_ADDRESS_WIDTH_32) { Hv_Cal_Qspi_DmaRead(pstQspi, aucCmdAddr, 5, pucRxData, uiRxSize); } return HV_SUCCESS; } /**********************************************Quad API end *************************************/ /**********************************************flash db opration ********************************/ static QspiSelf* Flash_GetQspi(FlashSelf* pstFlash) { QspiSelf* pstQspi = pstFlash->pstQspi; return pstQspi; } static Status Flash_SetBaudRate(FlashSelf* pstFlash,USHORT16 baudRate) { QspiSelf* pstQspi = pstFlash->pstQspi; Hv_Cal_Qspi_SetBaudRate(pstQspi,(QspiDivideRatio)baudRate); return HV_SUCCESS; } static FlashMultiIOType Flash_GetTransType(FlashSelf* pstFlash) { return pstFlash->InitParam.TransType; } static FlashAddressWidth Flash_GetAddrWidth(void* arg) { FlashSelf* pstFlash = (FlashSelf*)arg; return pstFlash->InitParam.AddrWidth; } static FlashDataWidth Flash_GetDataSize(FlashSelf* pstFlash) { return pstFlash->InitParam.DataSize; } static FlashRateMode Flash_GetRateMode(FlashSelf* pstFlash) { return pstFlash->InitParam.RateMode; } static FlashAttribute* Flash_GetFlashAttribute(void* arg) { FlashSelf* pstFlash = (FlashSelf*)arg; return &pstFlash->flashAttr; } static Status Flash_FourLineEnable(FlashSelf* pstFlash,FlashModel enFlashModel) { QspiSelf* pstQspi = Flash_GetQspi(pstFlash); UCHAR8 switchCmd[4] = {0}; if (enFlashModel == FLASH_GD25) { switchCmd[0] = GD25_Flash_QuadEnable & 0xff; switchCmd[1] = 0x00 & 0xff; switchCmd[2] = 0x02 & 0xff; Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 3, NULL, 0, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_QUAD); //HV_LOGI("GD25 flash quad mode is enable.\n"); } else if (enFlashModel == FLASH_P25Q) { switchCmd[0] = P25Q_Flash_QuadEnable & 0xff; switchCmd[1] = 0x02 & 0xff; Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 2, NULL, 0, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_QUAD); //HV_LOGI("P25Q flash quad mode is enable.\n"); } else if (enFlashModel == FLASH_MX25) { if ((Flash_GetTransType(pstFlash) == FLASH_MULTIIO_FAST_TYPE) ||(Flash_GetTransType(pstFlash) == FLASH_ADDR_4LINE)) { UCHAR8 aucStateCmd[2] = {0x05,0x00}; UCHAR8 aucRdState[2] = {0xff,0xff}; Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); Hv_Cal_Qspi_PollingRead(pstQspi, aucStateCmd, 2, aucRdState, 0, FLASH_TIMEOUT); // HV_LOGI("regVal[0] is 0x%x,regVal[1] is 0x%x.\n",aucRdState[0],aucRdState[1]); if ((aucRdState[1] & 0x40) != 0x40) { switchCmd[0]=0x01; switchCmd[1]=0x40; Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 2, NULL, 0, FLASH_TIMEOUT); } Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_QUAD); //HV_LOGI("MX25Q flash quad mode is enable.\n"); } else if (Flash_GetTransType(pstFlash) == FLASH_INSTRUCT_ADDR_4LINE) { switchCmd[0] = MX25_Flash_QpiEnable & 0xff; Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 1, NULL, 0, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_QUAD); //HV_LOGI("MX25Q flash qpi mode is enable.\n"); } } else if (enFlashModel == FLASH_W25Q) { UCHAR8 aucStateCmd[2] = {0x35,0x00}; UCHAR8 aucRdState[2] = {0xff,0xff}; UCHAR8 RdStateVerify[2] = {0xff,0xff}; Hv_Cal_Qspi_SetRateMode(pstQspi, QSPI_STANDARD); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); Hv_Cal_Qspi_PollingRead(pstQspi, aucStateCmd, 2, aucRdState, 0, FLASH_TIMEOUT); HV_LOGI("regVal[0] is 0x%x,regVal[1] is 0x%x.\n",aucRdState[0],aucRdState[1]); if ((aucRdState[1] & 0x02) != 0x02) { switchCmd[0]=0x01; switchCmd[1]=0x00; switchCmd[2]=0x02; Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 3, NULL, 0, FLASH_TIMEOUT); } Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); Hv_Cal_Qspi_PollingRead(pstQspi, aucStateCmd, 2, RdStateVerify, 0, FLASH_TIMEOUT); HV_LOGI("regVal[0] is 0x%x,regVal[1] is 0x%x.\n",RdStateVerify[0],RdStateVerify[1]); Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_QUAD); HV_LOGI("W25Q flash quad mode is enable.\n"); } return HV_SUCCESS; } static VOID Flash_ReadStatusReg(UCHAR8 ucReg, UCHAR8* pucVal, UCHAR8 ucLen) { QspiSelf* pstQspi = Flash_GetQspi(&g_stFlash); FlashRateMode RateMode = g_stFlash.InitParam.RateMode; Hv_Cal_Qspi_SetRateMode(pstQspi, QSPI_STANDARD); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingRead(pstQspi, &ucReg, 1, pucVal, ucLen, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi,RateMode); HV_LOGV("read status is 0x%x:0x%x.\n",ucReg, *pucVal); return; } static VOID Flash_WriteStatusReg(UCHAR8 ucReg, UCHAR8 ucVal) { UCHAR8 switchCmd[2] = {0}; switchCmd[0] = ucReg; switchCmd[1] = ucVal; QspiSelf* pstQspi = Flash_GetQspi(&g_stFlash); FlashRateMode RateMode = g_stFlash.InitParam.RateMode; Flash_WriteEnable(&g_stFlash); Hv_Cal_Qspi_SetRateMode(pstQspi, QSPI_STANDARD); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 2, NULL, 0, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi,RateMode); HV_LOGV("write status is 0x%x:0x%x.\n",ucReg, ucVal); return; } static VOID Flash_WriteStatusRegDB(UCHAR8 ucReg, UCHAR8 pucLow, UCHAR8 pucHigh) { UCHAR8 switchCmd[3] = {0}; switchCmd[0] = ucReg; switchCmd[1] = pucLow; switchCmd[2] = pucHigh; QspiSelf* pstQspi = Flash_GetQspi(&g_stFlash); FlashRateMode RateMode = g_stFlash.InitParam.RateMode; Flash_WriteEnable(&g_stFlash); Hv_Cal_Qspi_SetRateMode(pstQspi, QSPI_STANDARD); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 3, NULL, 0, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi,RateMode); HV_LOGV("write status is 0x%x:0x%x.0x%x\n",ucReg, pucLow, pucHigh); return; } static VOID Flash_WriteAddrProtect(UINT32 uiFlashID, UINT32 uiAddr, UCHAR8 ucProtectDisable) { UCHAR8 ucStatus = 0; UCHAR8 ucNeedWp = 0; UCHAR8 aucStatus[3] = {0x0}; HV_LOGV("ucProtectDisable 0x%x:0x%x\n",ucProtectDisable, uiAddr); switch (uiFlashID) { /* mx25v1635 bit2-bit5:bp0-bp3 tb bit use 0 default. */ case 0xc22315: { Flash_ReadStatusReg(0x05, &ucStatus, 1); if (1 == ucProtectDisable) { /* 1 1 1 0 protect:0-30 */ if (uiAddr >= 0x1f0000) { ucStatus |= 0xe << 2; ucStatus &= ~(0x1 << 2); } /* 1 1 0 1 protect:0-29 */ else if (uiAddr >= 0x1e0000) { ucStatus |= 0xd << 2; ucStatus &= ~(0x2 << 2); } /* 1 1 0 0 protect:0-27 */ else if (uiAddr >= 0x1c0000) { ucStatus |= 0xc << 2; ucStatus &= ~(0x3 << 2); } /* 1 0 1 1 protect:0-23 */ else if (uiAddr >= 0x180000) { ucStatus |= 0xb << 2; ucStatus &= ~(0x4 << 2); } /* 1 0 1 0 protect:0-16 */ else if (uiAddr >= 0x100000) { ucStatus |= 0xc << 2; ucStatus &= ~(0x5 << 2); } /* 0 1 0 1 protect:16-31 */ else { ucStatus |= 0x5 << 2; ucStatus &= ~(0xa << 2); } /* set swrd bit. */ ucStatus |= 0x1 << 7; Flash_WriteStatusRegDB(0x01, ucStatus, 0); } else if (0xaa == ucProtectDisable) { /* 0 0 0 0*/ ucStatus &= ~ (0xf << 2); /* set swrd bit. */ ucStatus &= ~ (0x1 << 7); Flash_WriteStatusRegDB(0x01, ucStatus, 0); } else { /* 1 1 1 1*/ ucStatus |= 0xf << 2; /* set swrd bit. */ ucStatus |= 0x1 << 7; Flash_WriteStatusRegDB(0x01, ucStatus, 0); } Hv_Vos_MSleep(40); break; } /* mx25l1606e.mx25v16066 bit2-bit5:bp0-bp3 */ case 0xc22015: { Flash_ReadStatusReg(0x05, &ucStatus, 1); if (1 == ucProtectDisable) { /* 1 1 1 0 protect:0-30 */ if (uiAddr >= 0x1f0000) { ucStatus |= 0xe << 2; ucStatus &= ~(0x1 << 2); } /* 1 1 0 1 protect:0-29 */ else if (uiAddr >= 0x1e0000) { ucStatus |= 0xd << 2; ucStatus &= ~(0x2 << 2); } /* 1 1 0 0 protect:0-27 */ else if (uiAddr >= 0x1c0000) { ucStatus |= 0xc << 2; ucStatus &= ~(0x3 << 2); } /* 1 0 1 1 protect:0-23 */ else if (uiAddr >= 0x180000) { ucStatus |= 0xb << 2; ucStatus &= ~(0x4 << 2); } /* 1 0 1 0 protect:0-16 */ else if (uiAddr >= 0x100000) { ucStatus |= 0xc << 2; ucStatus &= ~(0x5 << 2); } /* 0 1 0 1 protect:16-31 */ else { ucStatus |= 0x5 << 2; ucStatus &= ~(0xa << 2); } /* set swrd bit. */ ucStatus |= 0x1 << 7; Flash_WriteStatusReg(0x01, ucStatus); } else if (0xaa == ucProtectDisable) { /* 0 0 0 0*/ ucStatus &= ~ (0xf << 2); /* set swrd bit. */ ucStatus &= ~ (0x1 << 7); Flash_WriteStatusReg(0x01, ucStatus); } else { /* 1 1 1 1*/ ucStatus |= 0xf << 2; /* set swrd bit. */ ucStatus |= 0x1 << 7; Flash_WriteStatusReg(0x01, ucStatus); } Hv_Vos_MSleep(40); break; } /* XM25QH16C bit14:bmp bit2-bit6:bp0-bp4*/ case 0x204015: { Flash_ReadStatusReg(0x05, &aucStatus[0], 1); Flash_ReadStatusReg(0x35, &aucStatus[1], 1); if (1 == ucProtectDisable) { /* cmp 1, 1 0 0 0 1 protect:0-31 */ if (uiAddr >= 0x1ff000) { aucStatus[0] |= 0x11 << 2; aucStatus[0] &= ~(0xe << 2); } /* cmp 1, 1 0 0 1 0 protect:0-31 */ else if (uiAddr >= 0x1fe000) { aucStatus[0] |= 0x12 << 2; aucStatus[0] &= ~(0xd << 2); } /* cmp 1, 1 0 0 1 1 protect:0-31 */ else if (uiAddr >= 0x1fc000) { aucStatus[0] |= 0x13 << 2; aucStatus[0] &= ~(0xc << 2); } /* cmp 1, 1 0 1 0 x protect:0-31 */ else if (uiAddr >= 0x1f8000) { aucStatus[0] |= 0x14 << 2; aucStatus[0] &= ~(0xa << 2); } /* cmp 1, 0 0 0 0 1 protect:0-30 */ else if (uiAddr >= 0x1f0000) { aucStatus[0] |= 0x1 << 2; aucStatus[0] &= ~(0x1e << 2); } /* cmp 1, 0 0 0 1 0 protect:0-29 */ else if (uiAddr >= 0x1e0000) { aucStatus[0] |= 0x2 << 2; aucStatus[0] &= ~(0x1d << 2); } /* cmp 1, 0 0 0 1 1 protect:0-27 */ else if (uiAddr >= 0x1c0000) { aucStatus[0] |= 0x3 << 2; aucStatus[0] &= ~(0x1c << 2); } /* cmp 1, 0 0 1 0 0 protect:0-23 */ else if (uiAddr >= 0x180000) { aucStatus[0] |= 0x4 << 2; aucStatus[0] &= ~(0x1b << 2); } /* cmp 1, 0 0 1 0 1 protect:0-15 */ else if (uiAddr >= 0x100000) { aucStatus[0] |= 0x5 << 2; aucStatus[0] &= ~(0x1a << 2); } /* cmp 1, 1 1 0 0 1 protect:0-31 */ else if (uiAddr < 0x1000) { aucStatus[0] |= 0x19 << 2; aucStatus[0] &= ~(0x6 << 2); } /* cmp 1, 1 1 0 1 0 protect:0-31 */ else if (uiAddr < 0x2000) { aucStatus[0] |= 0x1a << 2; aucStatus[0] &= ~(0x5 << 2); } /* cmp 1, 1 1 0 1 1 protect:0-31 */ else if (uiAddr < 0x4000) { aucStatus[0] |= 0x1b << 2; aucStatus[0] &= ~(0x4 << 2); } /* cmp 1, 1 1 1 0 x protect:0-31 */ else if (uiAddr < 0x8000) { aucStatus[0] |= 0x1c << 2; aucStatus[0] &= ~(0x3 << 2); } /* cmp 1, 0 1 0 0 1 protect:1-31 */ else if (uiAddr < 0x10000) { aucStatus[0] |= 0x9 << 2; aucStatus[0] &= ~(0x16 << 2); } /* cmp 1, 0 1 0 1 0 protect:2-31 */ else if (uiAddr < 0x20000) { aucStatus[0] |= 0xa << 2; aucStatus[0] &= ~(0x15 << 2); } /* cmp 1, 0 1 0 1 1 protect:4-31 */ else if (uiAddr < 0x40000) { aucStatus[0] |= 0xb << 2; aucStatus[0] &= ~(0x14 << 2); } /* cmp 1, 0 1 1 0 0 protect:8-31 */ else if (uiAddr < 0x80000) { aucStatus[0] |= 0xc << 2; aucStatus[0] &= ~(0x13 << 2); } /* cmp 1, 0 1 1 0 1 protect:16-31 */ else //(uiAddr < 0x100000) { aucStatus[0] |= 0xd << 2; aucStatus[0] &= ~(0x12 << 2); } /* set srp0 1 & srp1 0. */ aucStatus[0] |= 1 << 7; aucStatus[1] &= ~ (0x1); /* set cmp bit 1. */ aucStatus[1] |= 0x1 << 6; /* close qe */ aucStatus[1] &= ~ (0x1 << 1); Flash_WriteStatusReg(0x31, aucStatus[1]); Hv_Vos_MSleep(10); Flash_WriteStatusReg(0x01, aucStatus[0]); Hv_Vos_MSleep(10); } else if (0xaa == ucProtectDisable) { /* cmp 0, x x 0 0 0 */ aucStatus[0] &= ~ (0x7 << 2); aucStatus[1] &= ~(0x1 << 6); /* set srp0 0 & srp1 0. */ aucStatus[0] &= ~ (1 << 7); aucStatus[1] &= ~ (0x1); /* close qe */ aucStatus[1] &= ~ (0x1 << 1); Flash_WriteStatusReg(0x01, 0); Hv_Vos_MSleep(10); Flash_WriteStatusReg(0x31, 0); } else { /* cmp 0, x x 1 1 x */ aucStatus[0] |= 0x6 << 2; aucStatus[1] &= ~(0x1 << 6); /* set srp0 1 & srp1 0. */ aucStatus[0] |= 1 << 7; aucStatus[1] &= ~ (0x1); /* close qe */ aucStatus[1] &= ~ (0x1 << 1); Flash_WriteStatusReg(0x01, aucStatus[0]); Hv_Vos_MSleep(10); Flash_WriteStatusReg(0x31, aucStatus[1]); } Hv_Vos_MSleep(50); break; } /* GD25Q16E bit14:bmp bit2-bit6:bp0-bp4*/ case 0xc84015: { Flash_ReadStatusReg(0x05, &aucStatus[0], 1); Flash_ReadStatusReg(0x35, &aucStatus[1], 1); if (1 == ucProtectDisable) { /* cmp 1, 1 0 0 0 1 protect:0-31 */ if (uiAddr >= 0x1ff000) { aucStatus[0] |= 0x11 << 2; aucStatus[0] &= ~(0xe << 2); } /* cmp 1, 1 0 0 1 0 protect:0-31 */ else if (uiAddr >= 0x1fe000) { aucStatus[0] |= 0x12 << 2; aucStatus[0] &= ~(0xd << 2); } /* cmp 1, 1 0 0 1 1 protect:0-31 */ else if (uiAddr >= 0x1fc000) { aucStatus[0] |= 0x13 << 2; aucStatus[0] &= ~(0xc << 2); } /* cmp 1, 1 0 1 0 x protect:0-31 */ else if (uiAddr >= 0x1f8000) { aucStatus[0] |= 0x14 << 2; aucStatus[0] &= ~(0xa << 2); } /* cmp 1, 0 0 0 0 1 protect:0-30 */ else if (uiAddr >= 0x1f0000) { aucStatus[0] |= 0x1 << 2; aucStatus[0] &= ~(0x1e << 2); } /* cmp 1, 0 0 0 1 0 protect:0-29 */ else if (uiAddr >= 0x1e0000) { aucStatus[0] |= 0x2 << 2; aucStatus[0] &= ~(0x1d << 2); } /* cmp 1, 0 0 0 1 1 protect:0-27 */ else if (uiAddr >= 0x1c0000) { aucStatus[0] |= 0x3 << 2; aucStatus[0] &= ~(0x1c << 2); } /* cmp 1, 0 0 1 0 0 protect:0-23 */ else if (uiAddr >= 0x180000) { aucStatus[0] |= 0x4 << 2; aucStatus[0] &= ~(0x1b << 2); } /* cmp 1, 0 0 1 0 1 protect:0-15 */ else if (uiAddr >= 0x100000) { aucStatus[0] |= 0x5 << 2; aucStatus[0] &= ~(0x1a << 2); } /* cmp 1, 1 1 0 0 1 protect:0-31 */ else if (uiAddr < 0x1000) { aucStatus[0] |= 0x19 << 2; aucStatus[0] &= ~(0x6 << 2); } /* cmp 1, 1 1 0 1 0 protect:0-31 */ else if (uiAddr < 0x2000) { aucStatus[0] |= 0x1a << 2; aucStatus[0] &= ~(0x5 << 2); } /* cmp 1, 1 1 0 1 1 protect:0-31 */ else if (uiAddr < 0x4000) { aucStatus[0] |= 0x1b << 2; aucStatus[0] &= ~(0x4 << 2); } /* cmp 1, 1 1 1 0 x protect:0-31 */ else if (uiAddr < 0x8000) { aucStatus[0] |= 0x1c << 2; aucStatus[0] &= ~(0x3 << 2); } /* cmp 1, 0 1 0 0 1 protect:1-31 */ else if (uiAddr < 0x10000) { aucStatus[0] |= 0x9 << 2; aucStatus[0] &= ~(0x16 << 2); } /* cmp 1, 0 1 0 1 0 protect:2-31 */ else if (uiAddr < 0x20000) { aucStatus[0] |= 0xa << 2; aucStatus[0] &= ~(0x15 << 2); } /* cmp 1, 0 1 0 1 1 protect:4-31 */ else if (uiAddr < 0x40000) { aucStatus[0] |= 0xb << 2; aucStatus[0] &= ~(0x14 << 2); } /* cmp 1, 0 1 1 0 0 protect:8-31 */ else if (uiAddr < 0x80000) { aucStatus[0] |= 0xc << 2; aucStatus[0] &= ~(0x13 << 2); } /* cmp 1, 0 1 1 0 1 protect:16-31 */ else //(uiAddr < 0x100000) { aucStatus[0] |= 0xd << 2; aucStatus[0] &= ~(0x12 << 2); } /* set srp0 1 & srp1 0. */ aucStatus[0] |= 1 << 7; aucStatus[1] &= ~ (0x1); /* set cmp bit 1. */ aucStatus[1] |= 0x1 << 6; /* close qe */ aucStatus[1] &= ~ (0x1 << 1); Flash_WriteStatusRegDB(0x01, aucStatus[0], aucStatus[1]); } else if (0xaa == ucProtectDisable) { /* cmp 0, x x 0 0 0 */ aucStatus[0] &= ~ (0x7 << 2); aucStatus[1] &= ~(0x1 << 6); /* set srp0 0 & srp1 0. */ aucStatus[0] &= ~ (1 << 7); aucStatus[1] &= ~ (0x1); /* close qe */ aucStatus[1] &= ~ (0x1 << 1); Flash_WriteStatusRegDB(0x01, aucStatus[0], aucStatus[1]); } else { /* cmp 0, x x 1 1 x */ if ((aucStatus[0] & 0x18) != 0x18) { ucNeedWp = 1; } if ((aucStatus[1] & 0x40) == 0x40) { ucNeedWp = 1; } HV_LOGV("wp status %x, %x", aucStatus[0], aucStatus[1]); aucStatus[0] |= 0x6 << 2; aucStatus[1] &= ~(0x1 << 6); /* set srp0 1 & srp1 0. */ aucStatus[0] |= 1 << 7; aucStatus[1] &= ~ (0x1); /* close qe */ aucStatus[1] &= ~ (0x1 << 1); if (ucNeedWp) { HV_LOGV("##need wp"); Flash_WriteStatusRegDB(0x01, aucStatus[0], aucStatus[1]); Hv_Vos_MSleep(30); } } break; } /* winbond w25q16 bit18:wps bit14:cmp bit2-bit6:sec,tb,bp0-bp3*/ case 0xef4015: { Flash_ReadStatusReg(0x05, &aucStatus[0], 1); Flash_ReadStatusReg(0x35, &aucStatus[1], 1); Flash_ReadStatusReg(0x15, &aucStatus[2], 1); if (1 == ucProtectDisable) { #if 0 /* cmp 1, 1 0 0 0 1 protect:0-31 */ if (uiAddr >= 0x1ff000) { aucStatus[0] |= 0x11 << 2; aucStatus[0] &= ~(0xe << 2); } /* cmp 1, 1 0 0 1 0 protect:0-31 */ else if (uiAddr >= 0x1fe000) { aucStatus[0] |= 0x12 << 2; aucStatus[0] &= ~(0xd << 2); } /* cmp 1, 1 0 0 1 1 protect:0-31 */ else if (uiAddr >= 0x1fc000) { aucStatus[0] |= 0x13 << 2; aucStatus[0] &= ~(0xc << 2); } /* cmp 1, 1 0 1 0 x protect:0-31 */ else if (uiAddr >= 0x1f8000) { aucStatus[0] |= 0x14 << 2; aucStatus[0] &= ~(0xa << 2); } /* cmp 1, 0 0 0 0 1 protect:0-30 */ else if (uiAddr >= 0x1f0000) { aucStatus[0] |= 0x1 << 2; aucStatus[0] &= ~(0x1e << 2); } /* cmp 1, 0 0 0 1 0 protect:0-29 */ else if (uiAddr >= 0x1e0000) { aucStatus[0] |= 0x2 << 2; aucStatus[0] &= ~(0x1d << 2); } /* cmp 1, 0 0 0 1 1 protect:0-27 */ else if (uiAddr >= 0x1c0000) { aucStatus[0] |= 0x3 << 2; aucStatus[0] &= ~(0x1c << 2); } /* cmp 1, 0 0 1 0 0 protect:0-23 */ else if (uiAddr >= 0x180000) { aucStatus[0] |= 0x4 << 2; aucStatus[0] &= ~(0x1b << 2); } /* cmp 1, 0 0 1 0 1 protect:0-15 */ else if (uiAddr >= 0x100000) { aucStatus[0] |= 0x5 << 2; aucStatus[0] &= ~(0x1a << 2); } /* cmp 1, 1 1 0 0 1 protect:0-31 */ else if (uiAddr < 0x1000) { aucStatus[0] |= 0x19 << 2; aucStatus[0] &= ~(0x6 << 2); } /* cmp 1, 1 1 0 1 0 protect:0-31 */ else if (uiAddr < 0x2000) { aucStatus[0] |= 0x1a << 2; aucStatus[0] &= ~(0x5 << 2); } /* cmp 1, 1 1 0 1 1 protect:0-31 */ else if (uiAddr < 0x4000) { aucStatus[0] |= 0x1b << 2; aucStatus[0] &= ~(0x4 << 2); } /* cmp 1, 1 1 1 0 x protect:0-31 */ else if (uiAddr < 0x8000) { aucStatus[0] |= 0x1c << 2; aucStatus[0] &= ~(0x3 << 2); } /* cmp 1, 0 1 0 0 1 protect:1-31 */ else if (uiAddr < 0x10000) { aucStatus[0] |= 0x9 << 2; aucStatus[0] &= ~(0x16 << 2); } /* cmp 1, 0 1 0 1 0 protect:2-31 */ else if (uiAddr < 0x20000) { aucStatus[0] |= 0xa << 2; aucStatus[0] &= ~(0x15 << 2); } /* cmp 1, 0 1 0 1 1 protect:4-31 */ else if (uiAddr < 0x40000) { aucStatus[0] |= 0xb << 2; aucStatus[0] &= ~(0x14 << 2); } /* cmp 1, 0 1 1 0 0 protect:8-31 */ else if (uiAddr < 0x80000) { aucStatus[0] |= 0xc << 2; aucStatus[0] &= ~(0x13 << 2); } /* cmp 1, 0 1 1 0 1 protect:16-31 */ else //(uiAddr < 0x100000) { aucStatus[0] |= 0xd << 2; aucStatus[0] &= ~(0x12 << 2); } /* set srp0 1 & srp1 0. */ aucStatus[0] |= 1 << 7; aucStatus[1] &= ~ (0x1); /* set cmp bit 1. */ aucStatus[1] |= 0x1 << 6; /* close qe */ aucStatus[1] &= ~ (0x1 << 1); /* set wps 0 */ aucStatus[2] &= ~ (0x1 << 2); Flash_WriteStatusReg(0x01, aucStatus[0]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x31, aucStatus[1]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x11, aucStatus[2]); #else /* wps 0, cmp 0 , x x 0 0 0 srp: 0 srl: 0 qe:0 */ aucStatus[0] &= ~ (0x7 << 2); aucStatus[0] &= ~ (0x1 << 7); aucStatus[1] &= ~ (0x1 << 0); aucStatus[1] &= ~ (0x1 << 1); aucStatus[1] &= ~ (0x1 << 6); aucStatus[2] &= ~ (0x1 << 2); Flash_WriteStatusReg(0x01, aucStatus[0]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x31, aucStatus[1]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x11, aucStatus[2]); #endif } else if (0xaa == ucProtectDisable) { /* wps 0, cmp 0 , x x 0 0 0 srp: 0 srl: 0 qe:0 */ aucStatus[0] &= ~ (0x7 << 2); aucStatus[0] &= ~ (0x1 << 7); aucStatus[1] &= ~ (0x1 << 0); aucStatus[1] &= ~ (0x1 << 1); aucStatus[1] &= ~ (0x1 << 6); aucStatus[2] &= ~ (0x1 << 2); Flash_WriteStatusReg(0x01, aucStatus[0]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x31, aucStatus[1]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x11, aucStatus[2]); } else { /* wps 0, cmp 0 , x x 1 1 1 srp: 1 srl: 0 qe:0 */ aucStatus[0] |= 0x7 << 2; aucStatus[0] |= 0x1 << 7; aucStatus[1] &= ~ (0x1 << 0); aucStatus[1] &= ~ (0x1 << 1); aucStatus[1] &= ~ (0x1 << 6); aucStatus[2] &= ~ (0x1 << 2); Flash_WriteStatusReg(0x01, aucStatus[0]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x31, aucStatus[1]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x11, aucStatus[2]); } Hv_Vos_MSleep(15); break; } /* winbond w25q32 */ case 0xef4016: { Flash_ReadStatusReg(0x05, &aucStatus[0], 1); Flash_ReadStatusReg(0x35, &aucStatus[1], 1); Flash_ReadStatusReg(0x15, &aucStatus[2], 1); if (1 == ucProtectDisable) { /* wps 0, cmp 0 , x x 0 0 0 srp: 1 srl: 0 qe:0 */ aucStatus[0] &= ~ (0x7 << 2); aucStatus[0] |= 0x1 << 7; aucStatus[1] &= ~ (0x1 << 0); aucStatus[1] &= ~ (0x1 << 1); aucStatus[1] &= ~ (0x1 << 6); aucStatus[2] &= ~ (0x1 << 2); Flash_WriteStatusReg(0x01, aucStatus[0]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x31, aucStatus[1]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x11, aucStatus[2]); } else if (0xaa == ucProtectDisable) { /* wps 0, cmp 0 , x x 0 0 0 srp: 0 srl: 0 qe:0 */ aucStatus[0] &= ~ (0x7 << 2); aucStatus[0] &= ~ (0x1 << 7); aucStatus[1] &= ~ (0x1 << 0); aucStatus[1] &= ~ (0x1 << 1); aucStatus[1] &= ~ (0x1 << 6); aucStatus[2] &= ~ (0x1 << 2); Flash_WriteStatusReg(0x01, aucStatus[0]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x31, aucStatus[1]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x11, aucStatus[2]); } else { /* wps 0, cmp 0 , x x 1 1 1 srp: 1 srl: 0 qe:0 */ aucStatus[0] |= 0x7 << 2; aucStatus[0] |= 0x1 << 7; aucStatus[1] &= ~ (0x1 << 0); aucStatus[1] &= ~ (0x1 << 1); aucStatus[1] &= ~ (0x1 << 6); aucStatus[2] &= ~ (0x1 << 2); Flash_WriteStatusReg(0x01, aucStatus[0]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x31, aucStatus[1]); Hv_Vos_MSleep(15); Flash_WriteStatusReg(0x11, aucStatus[2]); } Hv_Vos_MSleep(15); break; } default: { break; } } } static UINT32 Flash_ReadFlashID(VOID) { QspiSelf* pstQspi = Flash_GetQspi(&g_stFlash); FlashRateMode RateMode = g_stFlash.InitParam.RateMode; UCHAR8 aucIDCmd[4] = {0x9f}; UCHAR8 aucReadID[4] = {0x0}; HV_LOGV("Flash_ReadFlashID.\n"); Hv_Cal_Qspi_WP_Enable(HV_FALSE); Hv_Cal_Qspi_SetRateMode(pstQspi, QSPI_STANDARD); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_32); Hv_Cal_Qspi_PollingRead(pstQspi, aucIDCmd, 4, aucReadID, 0, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi, RateMode); HV_LOGI("flash id: 0x%x 0x%x 0x%x.\n",aucReadID[1], aucReadID[2], aucReadID[3]); Hv_Cal_Qspi_WP_Enable(HV_TRUE); return (aucReadID[1]<<16 | aucReadID[2]<<8 | aucReadID[3]); } VOID Hv_Drv_Flash_ProtectDisable(VOID) { Hv_Cal_Qspi_WP_Enable(HV_FALSE); Flash_WriteAddrProtect(g_stFlash.uiFlashID, 0, 0xAA); Hv_Cal_Qspi_WP_Enable(HV_TRUE); return; } VOID Hv_Drv_Flash_Info(VOID) { UCHAR8 aucStatus[3] = {0x0}; Flash_ReadFlashID(); Hv_Vos_MSleep(5); Flash_ReadStatusReg(0x05, &aucStatus[0], 1); Flash_ReadStatusReg(0x35, &aucStatus[1], 1); Flash_ReadStatusReg(0x15, &aucStatus[2], 1); HV_LOGI("status: %x,%x,%x.\n", aucStatus[0],aucStatus[1], aucStatus[2]); return; } static Status Flash_WriteProtectEnable(VOID) { #ifdef HV_PROJECT_CONFIG_FLASH_PROTECT HV_LOGV("Flash_WriteProtectEnable.\n"); Hv_Cal_Qspi_WP_Enable(HV_FALSE); Flash_WriteAddrProtect(g_stFlash.uiFlashID, 0, HV_FALSE); Hv_Cal_Qspi_WP_Enable(HV_TRUE); #endif return HV_SUCCESS; } static Status Flash_WriteProtectDisable(UINT32 uiAddr) { #ifdef HV_PROJECT_CONFIG_FLASH_PROTECT HV_LOGV("Flash_WriteProtectDisable.\n"); Hv_Cal_Qspi_WP_Enable(HV_FALSE); Flash_WriteAddrProtect(g_stFlash.uiFlashID, uiAddr, HV_TRUE); Hv_Cal_Qspi_WP_Enable(HV_TRUE); #endif return HV_SUCCESS; } static Status Flash_FourLineDisable(FlashSelf* pstFlash, FlashModel enFlashModel) { QspiSelf* pstQspi = Flash_GetQspi(pstFlash); UCHAR8 switchCmd[4] = {0}; if (enFlashModel == FLASH_GD25) { switchCmd[0] = GD25_Flash_QuadDisable & 0xff; switchCmd[1] = 0x00 & 0xff; switchCmd[2] = 0x00 & 0xff; Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 3, NULL, 0, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_QUAD); } else if (enFlashModel == FLASH_P25Q) { switchCmd[0] = P25Q_Flash_QuadDisable & 0xff; switchCmd[1] = 0x00 & 0xff; Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 2, NULL, 0, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_QUAD); } else if (enFlashModel == FLASH_MX25) { if ((Flash_GetTransType(pstFlash) == FLASH_MULTIIO_FAST_TYPE) || (Flash_GetTransType(pstFlash) == FLASH_ADDR_4LINE)) { UCHAR8 aucStateCmd[2] = {0x05,0x00}; UCHAR8 aucRdState[2] = {0xff,0xff}; Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); Hv_Cal_Qspi_PollingRead(pstQspi, aucStateCmd, 2, aucRdState, 0, FLASH_TIMEOUT); if ((aucRdState[1] & 0x40) == 0x40) { switchCmd[0]=0x01; switchCmd[1]=0x00; Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_16); // Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 2, NULL, 0, FLASH_TIMEOUT); } Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_QUAD); //HV_LOGI("MX25Q flash quad mode is disable.\n"); } else if (Flash_GetTransType(pstFlash) == FLASH_INSTRUCT_ADDR_4LINE) { switchCmd[0] = MX25_Flash_QpiDisable & 0xff; Flash_WriteEnable(pstFlash); Hv_Cal_Qspi_PollingWrite(pstQspi, switchCmd, 1, NULL, 0, FLASH_TIMEOUT); //HV_LOGI("MX25Q flash qpi mode is disable.\n"); } } return HV_SUCCESS; } static void Flash_DualFuctionJudge(FlashModel enFlashModel) { if (enFlashModel == FLASH_W25Q) { HV_LOGI("W25Q can't support dual mode fast write,can support dual mode fast read.\n"); } else if (enFlashModel == FLASH_GD25) { HV_LOGI("GD25 can't support dual mode fast write,can support dual mode fast read.\n"); } else if (enFlashModel == FLASH_MX25) { HV_LOGI("MX25 can't support dual mode fast write,can support dual mode fast read.\n"); } return; } /**********************************************flash db opration end*****************************/ /****************************** Flash Common API ************************************************/ static void FLASH_SetCpltCallBack(FlashSelf* pstFlash, void* callbackFunc) { QspiSelf* pstQspi = pstFlash->pstQspi; pstFlash->InitParam.FlashCpltCallback = (Flash_CpltCallback)callbackFunc; Hv_Cal_Qspi_SetCpltCallBack(pstQspi,Flash_CpltCallBack); } UCHAR8 Hv_Drv_Flash_GetFlashStatus(FlashSelf* pstFlash) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 ucRegVal = 0; UCHAR8 ucReadCmd = 0x05; if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingRead(pstQspi, &ucReadCmd, 1, &ucRegVal, 1, FLASH_TIMEOUT); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL ||pstFlash->InitParam.RateMode == FLASH_QUAD) { if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_RX); Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); Hv_Cal_Qspi_SetReadNumber(pstQspi, 1); Hv_Cal_Qspi_MultiIoPollingRead(pstQspi, &ucReadCmd, 1, &ucRegVal, 1, FLASH_TIMEOUT); } else if (pstFlash->InitParam.TransType == FLASH_MULTIIO_FAST_TYPE) { QspiRateMode enRateMode = Hv_Cal_Qspi_GetRateMode(pstQspi); Hv_Cal_Qspi_SetRateMode(pstQspi,QSPI_STANDARD); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TXRX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingRead(pstQspi, &ucReadCmd, 1, &ucRegVal, 1, FLASH_TIMEOUT); Hv_Cal_Qspi_SetRateMode(pstQspi,enRateMode); } } return ucRegVal; } UCHAR8 Hv_Drv_Flash_WriteStatus(FlashSelf* pstFlash, UCHAR8 flashStatus) { QspiSelf* pstQspi = pstFlash->pstQspi; UCHAR8 ucSendCmd = 0x01; UCHAR8 ucSendData = flashStatus; if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_PollingWrite(pstQspi, &ucSendCmd, 1, &ucSendData, 1, FLASH_TIMEOUT); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL ||pstFlash->InitParam.RateMode == FLASH_QUAD) { Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi, QSPI_BITWIDTH_8); Hv_Cal_Qspi_SetDirection(pstQspi, QSPI_DIRECTION_TX); if (pstFlash->InitParam.TransType == FLASH_INSTRUCT_ADDR_4LINE) { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_MULTI_ADDR_MULTI, pstFlash->flashAttr.FlashInstruWidth, 0, 0); } else { Hv_Cal_Qspi_SetMultiIOCtrl(pstQspi, QSPI_INSTRU_STAND_ADDR_STAND, pstFlash->flashAttr.FlashInstruWidth, 0, 0); } Hv_Cal_Qspi_MutiIoPollingWrite(pstQspi, &ucSendCmd, 1, &ucSendData, 1, FLASH_TIMEOUT); } return ucSendData; } static FlashSelf* Flash_InitParam(FlashInitParam* InitParam) { QspiSelf* pstQspi = NULL; QspiInitParam qspiInitParam; UINT32 uiFlashID = 0; HV_MEMSET(&qspiInitParam,0, sizeof(qspiInitParam)); if (InitParam->RateMode == FLASH_QPI) { InitParam->RateMode = FLASH_QUAD; InitParam->TransType = FLASH_INSTRUCT_ADDR_4LINE; } else if (InitParam->RateMode == FLASH_4XIO) { InitParam->RateMode = FLASH_QUAD; InitParam->TransType = FLASH_ADDR_4LINE; } else { InitParam->TransType = FLASH_MULTIIO_FAST_TYPE; } qspiInitParam.RateMode = (QspiRateMode)InitParam->RateMode; qspiInitParam.Direction = QSPI_DIRECTION_TXRX; qspiInitParam.CLKPolarity = QSPI_POLARITY_LOW; qspiInitParam.CLKPhase = QSPI_PHASE_EDGE1; qspiInitParam.DataSize = (QspiBitWidth)(InitParam->DataSize - 1); qspiInitParam.CsSel = (QspiCsSel)(InitParam->CsSel); //Flash_SetCommonBaudRate(&qspiInitParam,InitParam); qspiInitParam.BaudRatePrescaler = QSPI_DIVRATIO_16; pstQspi = Hv_Cal_Qspi_Init(&qspiInitParam); if(NULL != pstQspi) { g_stFlash.pstQspi = pstQspi; } else { return NULL; } Hv_Cal_Qspi_SetFlashPoint(pstQspi,(void*)&g_stFlash); HV_MEMCPY(&(g_stFlash.InitParam), InitParam, sizeof(*InitParam)); if (InitParam->FlashCallback != NULL) { FLASH_SetCpltCallBack(&g_stFlash,InitParam->FlashCallback); } Hv_Drv_FlashDB_GetAttribute(&(g_stFlash.flashAttr),InitParam->FlashModel); if (InitParam->RateMode == FLASH_DUAL) { Flash_DualFuctionJudge(InitParam->FlashModel); } uiFlashID = Flash_ReadFlashID(); g_stFlash.uiFlashID = uiFlashID; if (InitParam->RateMode == FLASH_QUAD) { Flash_FourLineEnable(&g_stFlash,InitParam->FlashModel); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi,qspiInitParam.DataSize); } #ifdef HV_PROJECT_CONFIG_FLASH_PROTECT else { Hv_Cal_Qspi_WP_Init(); Flash_WriteProtectEnable(); } #endif return &g_stFlash; } static Status Flash_ReInit(FlashSelf* pstFlash, FlashWorkModeSel WorkModeSel, FlashRateMode RateMode,FlashDataWidth DataSize) { QspiSelf* pstQspi = pstFlash->pstQspi; QspiInitParam qspiInitParam; HV_MEMSET(&qspiInitParam,0, sizeof(qspiInitParam)); pstFlash->InitParam.WorkModeSel = WorkModeSel; pstFlash->InitParam.RateMode = RateMode; pstFlash->InitParam.DataSize = DataSize; if (pstFlash->InitParam.RateMode == FLASH_QPI) { pstFlash->InitParam.RateMode = FLASH_QUAD; pstFlash->InitParam.TransType = FLASH_INSTRUCT_ADDR_4LINE; } else if (pstFlash->InitParam.RateMode == FLASH_4XIO) { pstFlash->InitParam.RateMode = FLASH_QUAD; pstFlash->InitParam.TransType = FLASH_ADDR_4LINE; } else { pstFlash->InitParam.TransType = FLASH_MULTIIO_FAST_TYPE; } qspiInitParam.RateMode = (QspiRateMode)RateMode; qspiInitParam.DataSize = (QspiBitWidth)(DataSize - 1); Flash_SetCommonBaudRate(&qspiInitParam,&pstFlash->InitParam); Hv_Cal_Qspi_SetRateMode(pstQspi,qspiInitParam.RateMode); Hv_Cal_Qspi_SetFrameBitsWidth(pstQspi,qspiInitParam.DataSize); Hv_Cal_Qspi_SetBaudRate(pstQspi,qspiInitParam.BaudRatePrescaler); return HV_SUCCESS; } static Status _Flash_Cleanup(FlashSelf* pstFlash) { QspiSelf* pstQspi = pstFlash->pstQspi; if (pstFlash->InitParam.RateMode == FLASH_QUAD) { Flash_FourLineDisable(pstFlash,pstFlash->InitParam.FlashModel); } Hv_Cal_Qspi_Cleanup(pstQspi); return HV_SUCCESS; } UINT32 Hv_Drv_Flash_GetFlashID(FlashSelf* pstFlash) { UINT32 uiFlashID = 0; if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { uiFlashID = Flash_ReadID_Standard(pstFlash); } else if ((pstFlash->InitParam.RateMode == FLASH_DUAL) || (pstFlash->InitParam.RateMode == FLASH_QUAD)) { uiFlashID = Flash_ReadID_MutiIO(pstFlash); } return uiFlashID; } static Status _Flash_Erase(FlashSelf* pstFlash, FlashEraseType enEraseType,UINT32 uiEraseAddr) { if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Flash_EraseStandard(pstFlash, enEraseType, uiEraseAddr); } else if ((pstFlash->InitParam.RateMode == FLASH_DUAL) || (pstFlash->InitParam.RateMode == FLASH_QUAD)) { Flash_EraseMultiIo(pstFlash, enEraseType, uiEraseAddr); } return HV_SUCCESS; } static Status _Flash_Write(FlashSelf* pstFlash, UINT32 uiWtAddr, UCHAR8* pucTxData, UINT32 uiTxSize) { if (pstFlash->InitParam.WorkModeSel == FLASH_USE_POLLING) { if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Flash_SendStandard(pstFlash, uiWtAddr, pucTxData, uiTxSize); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL) { Flash_SendDual(pstFlash, uiWtAddr, pucTxData, uiTxSize); } else if (pstFlash->InitParam.RateMode == FLASH_QUAD) { Flash_SendQuad(pstFlash, uiWtAddr, pucTxData, uiTxSize); } } else if (pstFlash->InitParam.WorkModeSel == FLASH_USE_INT) { if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Flash_SendStandardInt(pstFlash, uiWtAddr, pucTxData, uiTxSize); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL) { Flash_SendDualInt(pstFlash, uiWtAddr, pucTxData, uiTxSize); } else if (pstFlash->InitParam.RateMode == FLASH_QUAD) { Flash_SendQuadInt(pstFlash, uiWtAddr, pucTxData, uiTxSize); } } else if (pstFlash->InitParam.WorkModeSel == FLASH_USE_DMA) { if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Flash_SendStandardDma(pstFlash, uiWtAddr, pucTxData, uiTxSize); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL) { Flash_SendDualDma(pstFlash, uiWtAddr, pucTxData, uiTxSize); } else if (pstFlash->InitParam.RateMode == FLASH_QUAD) { Flash_SendQuadDma(pstFlash, uiWtAddr, pucTxData, uiTxSize); } } return HV_SUCCESS; } static Status _Flash_Read(FlashSelf* pstFlash, UINT32 uiRdAddr, UCHAR8* pucRxData, UINT32 uiRxSize) { if (pstFlash->InitParam.WorkModeSel == FLASH_USE_POLLING) { if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Flash_RecvStandard(pstFlash, uiRdAddr, pucRxData, uiRxSize); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL) { Flash_RecvDual(pstFlash, uiRdAddr, pucRxData, uiRxSize); } else if (pstFlash->InitParam.RateMode == FLASH_QUAD) { Flash_RecvQuad(pstFlash, uiRdAddr, pucRxData, uiRxSize); } } else if (pstFlash->InitParam.WorkModeSel == FLASH_USE_INT) { if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Flash_RecvStandardInt(pstFlash, uiRdAddr, pucRxData,uiRxSize); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL) { Flash_RecvDualInt(pstFlash, uiRdAddr, pucRxData, uiRxSize); } else if (pstFlash->InitParam.RateMode == FLASH_QUAD) { Flash_RecvQuadInt(pstFlash, uiRdAddr, pucRxData, uiRxSize); } } else if (pstFlash->InitParam.WorkModeSel == FLASH_USE_DMA) { if (pstFlash->InitParam.RateMode == FLASH_STANDARD) { Flash_RecvStandardDma(pstFlash, uiRdAddr, pucRxData, uiRxSize); } else if (pstFlash->InitParam.RateMode == FLASH_DUAL) { Flash_RecvDualDma(pstFlash, uiRdAddr, pucRxData, uiRxSize); } else if (pstFlash->InitParam.RateMode == FLASH_QUAD) { Flash_RecvQuadDma(pstFlash, uiRdAddr, pucRxData, uiRxSize); } } return HV_SUCCESS; } BOOL Hv_Drv_Flash_TransferIsComplete(FlashSelf *pstFlash) { QspiSelf* pstQspi = pstFlash->pstQspi; return Hv_Cal_Qspi_TransferIsComplete(pstQspi); } static void Flash_Swap32(UCHAR8* pucSrc, UINT32 uiLength) { UINT32 uiLoop = 0; if ((uiLength % 4) != 0) { return; } for (uiLoop = 0; uiLoop < uiLength / 4; uiLoop++) { *((UINT32 *)(pucSrc + uiLoop * 4)) = HV_SWAP32(*((UINT32 *)(pucSrc + uiLoop * 4))); } return; } static void Flash_TxDmaInit(void) { QspiSelf *pstQspi = Flash_GetQspi(g_pFlash); DmaSelf* pstTxDma = NULL; DmaInitParam TxInitParam; Hv_Vos_Memset(&TxInitParam, 0, sizeof(DmaInitParam)); TxInitParam.PortChannelNum = DMA_PORT0_CHANNEL0; TxInitParam.Application = DMA_APPLI_QSPI0_TX; TxInitParam.transType = DMA_TYPE_SINGLE; pstTxDma = Hv_Cal_Dma_ChannelInit(&TxInitParam); Hv_Cal_Qspi_SetDmaTx(pstQspi, pstTxDma); return; } static void Flash_RxDmaInit(void) { QspiSelf *pstQspi = Flash_GetQspi(g_pFlash); DmaSelf* pstRxDma = NULL; DmaInitParam RxInitParam; Hv_Vos_Memset(&RxInitParam, 0, sizeof(DmaInitParam)); RxInitParam.PortChannelNum = DMA_PORT0_CHANNEL1; RxInitParam.Application = DMA_APPLI_QSPI0_RX; RxInitParam.transType = DMA_TYPE_SINGLE; pstRxDma = Hv_Cal_Dma_ChannelInit(&RxInitParam); Hv_Cal_Qspi_SetDmaRx(pstQspi,pstRxDma); return; } static void Flash_Program(UINT32 uiWriteAddr, UCHAR8* pucWriteBuf, UINT32 uiLength) { FlashTxMem stFlashMem; Hv_Vos_Memset(&stFlashMem, 0, sizeof(FlashTxMem)); if (((uiLength % 4) != 0) || (uiLength > PAGE_WRITE)) { return; } if (g_ucDmaUseFlag == HV_TRUE) { Hv_Vos_Memcpy((UCHAR8 *)stFlashMem.txData, (UCHAR8*)pucWriteBuf, uiLength); if (Flash_GetDataSize(g_pFlash) == FLASH_DATAWIDTH_32) { Flash_Swap32((UCHAR8 *)stFlashMem.txData,uiLength); } _Flash_Write(g_pFlash, uiWriteAddr, (UCHAR8 *)stFlashMem.txData, uiLength); while (Hv_Drv_Flash_TransferIsComplete(g_pFlash) == HV_FALSE); } else if (g_ucIntUseFlag == HV_TRUE) { _Flash_Write(g_pFlash, uiWriteAddr, pucWriteBuf, uiLength); while (Hv_Drv_Flash_TransferIsComplete(g_pFlash) == HV_FALSE); } else { _Flash_Write(g_pFlash, uiWriteAddr, pucWriteBuf, uiLength); } return; } static void Flash_Read(UINT32 uiReadAddr, UCHAR8 *pucReadBuf, UINT32 uiLength) { if (((uiLength % 4) != 0) ||(uiLength > PAGE_READ)) { return; } if (g_ucDmaUseFlag == HV_TRUE) { _Flash_Read(g_pFlash, uiReadAddr, g_ucReadBuf, uiLength); while (Hv_Drv_Flash_TransferIsComplete(g_pFlash)== HV_FALSE); Hv_Vos_MSleep(1); if (Flash_GetRateMode(g_pFlash) == FLASH_STANDARD) { Hv_Vos_Memcpy(pucReadBuf, &g_ucReadBuf[4], uiLength); } else { Hv_Vos_Memcpy(pucReadBuf, g_ucReadBuf, uiLength); } if (Flash_GetDataSize(g_pFlash) == FLASH_DATAWIDTH_32) { Flash_Swap32(pucReadBuf,uiLength); } } else if (g_ucIntUseFlag == HV_TRUE) { _Flash_Read(g_pFlash, uiReadAddr, pucReadBuf, uiLength); while (Hv_Drv_Flash_TransferIsComplete(g_pFlash)== HV_FALSE); } else { _Flash_Read(g_pFlash,uiReadAddr, pucReadBuf, uiLength); } return; } static void Flash_OnlyErase(UINT32 uiEraseAddr, UINT32 uiLength) { UINT32 uiLoop = 0; for (uiLoop = 0; uiLoop < (uiLength % ERASE_TYPE_SIZE == 0 ? (uiLength / ERASE_TYPE_SIZE) : (uiLength / ERASE_TYPE_SIZE + 1)); uiLoop++) { _Flash_Erase(g_pFlash, ERASE_TYPE, uiEraseAddr + uiLoop * ERASE_TYPE_SIZE); } } static void Flash_OnlyEraseMultiSector(UINT32 uiEraseAddr) { _Flash_Erase(g_pFlash, FLASH_ERASE_MULTI_SECTOR, uiEraseAddr); } static Status Flash_Check(UINT32 uiWriteAddr, UCHAR8 *pucWriteBuf, UINT32 uiLength) { UINT32 uiLoop = 0; UCHAR8 ucReadCrc = 0; UCHAR8 ucWriteCrc = 0; Flash_OnlyRead(uiWriteAddr, g_ucReadBuf, uiLength); for (uiLoop = 0; uiLoop < uiLength; uiLoop++) { if (*pucWriteBuf != g_ucReadBuf[uiLoop]) { HV_LOGI("[%2x]:need %x, act %x", uiLoop, *pucWriteBuf, g_ucReadBuf[uiLoop]); return HV_FAILURE; } pucWriteBuf++; } return HV_SUCCESS; } static Status Flash_OnlyWrite(UINT32 uiWriteAddr, UCHAR8 *pucWriteBuf, UINT32 uiLength) { UINT32 uiLoop = 0; UINT32 uiRemain = 0; UINT32 uiTempLen = 0; UINT32 uiTempAdd = 0; UINT32 uiRetry = 3; Status uiRet = HV_SUCCESS; UCHAR8* pucTmpUseWriteBuf = g_ucWriteBuf; HV_MEMSET(pucTmpUseWriteBuf, 0xff, PAGE_WRITE); for (uiLoop=0; uiLoop< uiLength / PAGE_WRITE; uiLoop++) { Hv_Vos_Memcpy(pucTmpUseWriteBuf, (UCHAR8 *)((UINT32)pucWriteBuf + uiLoop * PAGE_WRITE), PAGE_WRITE); Hv_Vos_InvalidAllDCache(); uiTempAdd = uiWriteAddr + uiLoop * PAGE_WRITE; uiRetry = 1; do { Flash_Program(uiTempAdd, pucTmpUseWriteBuf, PAGE_WRITE); if (HV_SUCCESS == Flash_Check(uiTempAdd, pucTmpUseWriteBuf, PAGE_WRITE)) { break; } HV_LOGV("flash write retry...\n"); uiRetry--; } while (uiRetry); if (0 == uiRetry) { uiRet = HV_FAILURE; HV_LOGE("flash write fail address %x\n", uiTempAdd); } } uiRemain = uiLength % PAGE_WRITE; if ((uiRemain > 0) && (uiRet == HV_SUCCESS)) { uiTempLen = (uiRemain % 4 == 0) ? (uiRemain / 4) : (uiRemain / 4 + 1); Hv_Vos_Memcpy(pucTmpUseWriteBuf, (UCHAR8 *)((UINT32)pucWriteBuf + (uiLength / PAGE_WRITE) * PAGE_WRITE), uiRemain); Hv_Vos_InvalidAllDCache(); uiRetry = 1; uiTempAdd = uiWriteAddr + (uiLength / PAGE_WRITE) * PAGE_WRITE; do { Flash_Program(uiTempAdd, pucTmpUseWriteBuf, uiTempLen * 4); if (HV_SUCCESS == Flash_Check(uiTempAdd, pucTmpUseWriteBuf, uiTempLen * 4)) { break; } HV_LOGV("flash write retry...\n"); } while ((uiRetry--) > 0); if (0 == uiRetry) { uiRet = HV_FAILURE; HV_LOGE("flash write fail address %x\n", uiTempAdd); } } return uiRet; } static void Flash_OnlyRead(UINT32 uiReadAddr, UCHAR8* pucReadBuf, UINT32 uiLength) { UINT32 uiLoop = 0; UINT32 uiRemain = 0; UINT32 uiTempLen = 0; UINT32 readCount = 0; HV_MEMSET(g_ucReadBuf, 0xff, PAGE_READ); Hv_Vos_InvalidAllDCache(); for (uiLoop=0; uiLoop < uiLength / PAGE_READ; uiLoop++) { Flash_Read(uiReadAddr + uiLoop * PAGE_READ, (UCHAR8*)((UINT32)pucReadBuf + uiLoop * PAGE_READ), PAGE_READ); readCount = readCount + PAGE_READ; } uiRemain = uiLength % PAGE_READ; if (uiRemain > 0) { if (g_ucDmaUseFlag == HV_TRUE) { uiTempLen = (uiRemain % 32 == 0)?(uiRemain):(uiRemain / 32 + 1) * 32; } else { uiTempLen = (uiRemain % 4 == 0) ? (uiRemain) : (uiRemain / 4 + 1) * 4; } Flash_Read(uiReadAddr + readCount, (UCHAR8*)g_ucReadBuf, uiTempLen); Hv_Vos_InvalidAllDCache(); Hv_Vos_Memcpy((UCHAR8*)((UINT32)pucReadBuf + readCount), g_ucReadBuf, uiRemain); Hv_Vos_InvalidAllDCache(); } return; } static BOOL Flash_EraseWrite(UINT32 uiWriteAddr, UCHAR8* pucWriteBuf, UINT32 uiLength) { UINT32 uiTempVal = 0; UINT32 uiFirstWriteSize = 0; UINT32 uiTempLen = uiLength; UCHAR8* pucWbuf = (UCHAR8*)pucWriteBuf; UCHAR8* pucTmpUseBuf = g_ucSectorBuf; UINT32 uiWaddr = uiWriteAddr; UINT32 uiCount = 0; Hv_Vos_AcquireSemaphore(g_pstFlashSeamphone); uiTempVal = uiWaddr & 0xfff; if ((uiTempVal) != 0) { if ((uiTempVal +uiTempLen) < SECTOR_SIZE) { HV_MEMSET(pucTmpUseBuf, 0xff, SECTOR_SIZE); Hv_Vos_InvalidAllDCache(); Flash_OnlyRead(uiWaddr & (~0xfff), pucTmpUseBuf, SECTOR_SIZE); Hv_Vos_Memcpy(&pucTmpUseBuf[uiTempVal],pucWbuf, uiTempLen); Hv_Vos_InvalidAllDCache(); Flash_OnlyErase(uiWaddr & (~0xfff), SECTOR_SIZE); Flash_OnlyWrite(uiWaddr & (~0xfff), pucTmpUseBuf, SECTOR_SIZE); uiTempLen = 0; } else { uiFirstWriteSize = SECTOR_SIZE - uiTempVal; Flash_OnlyRead(uiWaddr & (~0xfff), pucTmpUseBuf, SECTOR_SIZE); Hv_Vos_Memcpy(&pucTmpUseBuf[uiTempVal],pucWbuf, uiFirstWriteSize); Hv_Vos_InvalidAllDCache(); Flash_OnlyErase(uiWaddr & (~0xfff), SECTOR_SIZE); Flash_OnlyWrite(uiWaddr & (~0xfff), pucTmpUseBuf, SECTOR_SIZE); uiTempLen = uiTempLen - uiFirstWriteSize; uiWaddr = (uiWaddr & (~0xfff)) + SECTOR_SIZE; pucWbuf = pucWbuf + uiFirstWriteSize; } } while ((uiTempLen > SECTOR_SIZE) || (uiTempLen == SECTOR_SIZE)) { uiTempLen = uiTempLen- SECTOR_SIZE; uiCount++; } while (uiCount-- > 0) { Flash_OnlyErase(uiWaddr, SECTOR_SIZE * uiCount); Flash_OnlyWrite(uiWaddr, pucWbuf, SECTOR_SIZE * uiCount); uiWaddr = uiWaddr + SECTOR_SIZE * uiCount; pucWbuf = pucWbuf + SECTOR_SIZE * uiCount; } if (uiTempLen > 0) { Flash_OnlyRead(uiWaddr, pucTmpUseBuf, SECTOR_SIZE); Hv_Vos_Memcpy(pucTmpUseBuf, pucWbuf, uiTempLen); Hv_Vos_InvalidAllDCache(); Flash_OnlyErase(uiWaddr, SECTOR_SIZE); Flash_OnlyWrite(uiWaddr, pucTmpUseBuf, SECTOR_SIZE); //tmp fix } Hv_Vos_ReleaseSemaphore(g_pstFlashSeamphone); return HV_SUCCESS; } static void Flash_Init(FlashModel FlashModel, FlashRateMode RateMode, FlashWorkModeSel workMode) { FlashInitParam InitParam; InitParam.WorkModeSel = workMode; InitParam.FlashModel = FlashModel; InitParam.RateMode = RateMode; InitParam.FlashCallback = NULL; InitParam.CsSel = FLASH_CS_BY_GPIO; if (InitParam.FlashModel == FLASH_MX25) { InitParam.AddrWidth = FLASH_ADDRESS_WIDTH_32; if (InitParam.RateMode == FLASH_STANDARD) { InitParam.DataSize = FLASH_DATAWIDTH_8; } else if (InitParam.RateMode == FLASH_4XIO) { InitParam.DataSize = FLASH_DATAWIDTH_32; } else { HV_LOGI("MX25:Init config erro.\n"); HV_ASSERT(0); } } else if (InitParam.FlashModel == FLASH_GD25) { InitParam.AddrWidth = FLASH_ADDRESS_WIDTH_24; InitParam.DataSize = FLASH_DATAWIDTH_32; if ((InitParam.RateMode != FLASH_STANDARD) && (InitParam.RateMode != FLASH_DUAL) && (InitParam.RateMode != FLASH_QUAD)) { HV_LOGI("GD25:Init config erro.\n"); HV_ASSERT(0); } } else { InitParam.FlashModel = FLASH_MT25; InitParam.AddrWidth = FLASH_ADDRESS_WIDTH_24; InitParam.DataSize = FLASH_DATAWIDTH_32; if ((InitParam.RateMode != FLASH_STANDARD) && (InitParam.RateMode != FLASH_DUAL) && (InitParam.RateMode != FLASH_QUAD)) { HV_LOGI("MT25:Init config erro.\n"); HV_ASSERT(0); } } g_pFlash = Flash_InitParam(&InitParam); if (InitParam.WorkModeSel == FLASH_USE_DMA) { Flash_TxDmaInit(); Flash_RxDmaInit(); g_ucDmaUseFlag = HV_TRUE; g_ucIntUseFlag = HV_FALSE; } else if (InitParam.WorkModeSel == FLASH_USE_INT) { g_ucDmaUseFlag = HV_FALSE; g_ucIntUseFlag = HV_TRUE; } else if (InitParam.WorkModeSel == FLASH_USE_POLLING) { g_ucDmaUseFlag = HV_FALSE; g_ucIntUseFlag = HV_FALSE; } return; } static void Flash_CleanUp(void) { if (g_pFlash != NULL) { _Flash_Cleanup(g_pFlash); g_pFlash = NULL; } } /** * @brief write config data to flash. * @param uiAddress write offset at flash * @param pucData address write data to * @param uiDataSize write data size * @retval Status */ Status Hv_Drv_Flash_WriteMonitorData(UINT32 uiAddress, UCHAR8 *pucData, UINT32 uiDataSize) { Status sRet = HV_FAILURE; HV_LOGV("_Flash_Write uiAddress=%x,pucData=%x, uiDataSize= %d", uiAddress, pucData, uiDataSize); Flash_WriteProtectDisable(uiAddress); if (uiAddress >= HV_FLASH_CONFIG_MONITOR_DATA_PART_START) { sRet = Flash_EraseWrite(uiAddress, pucData, uiDataSize); } Flash_WriteProtectEnable(); return sRet; } /** * @brief read data from flash. * @param uiAddress read offset at flash * @param pucData address for read data * @param uiDataSize size to read data * @retval Status */ Status Hv_Drv_Flash_ReadMonitorData(UINT32 uiAddress, UCHAR8 *pucData, UINT32 uiDataSize) { HV_LOGV("_Flash_Read uiAddress=%x,pucData=0x%x, uiDataSize=%d", uiAddress, pucData, uiDataSize); if (uiAddress >= HV_FLASH_CONFIG_LOGO_PART_START) { Flash_OnlyRead(uiAddress, pucData, uiDataSize); return HV_SUCCESS; } return HV_FAILURE; } /** * @brief read data from flash in xip mode. * @param uiAddress read offset at flash * @param pucData address for read data * @param uiDataSize size to read data * @retval Status */ Status Hv_Drv_Flash_ReadXIP(UINT32 uiAddress, UCHAR8 *pucData, UINT32 uiDataSize) { UINT32 iLoop = 0; HV_LOGV("Hv_Drv_Flash_ReadXIP uiAddress=%x,pucData=0x%x, uiDataSize=%d", uiAddress, pucData, uiDataSize); { for (iLoop = 0; iLoop < uiDataSize; iLoop++) { *pucData = *((UCHAR8 *)(uiAddress + HV_FLASH_CONFIG_START_XIP + iLoop)); pucData++; } } return HV_SUCCESS; } /** * @brief int flash interface. */ void Hv_Drv_Flash_SetQspiMode(FlashModel FlashModel, FlashRateMode RateMode, FlashWorkModeSel workMode) { g_pstFlashSeamphone = Hv_Vos_InitSemaphore(1, 1); Flash_CleanUp(); Flash_Init(FlashModel, RateMode, workMode); } /** * @brief deint flash interface. */ void Hv_Drv_Flash_SetXipMode(void) { Flash_CleanUp(); return; } /** * @brief config logo data and pq etc data partition flag */ void Hv_Drv_Flash_ConfigPartFlag(void) { #ifdef SW_DUMMY_DEBUG /* add flash partition config */ HV_WT32(SW_DUMMY_LOGO, HV_FLASH_CONFIG_LOGO_PART_START); HV_WT32(SW_DUMMY_CONFIG_DATA, HV_FLASH_CONFIG_MONITOR_DATA_PART_START); HV_WT32(SW_DUMMY_PQ_DATA, HV_FLASH_CONFIG_PQ_DATA_PART_START); #endif return; } /** * @brief erase flash. * @param[in] uiWriteAddr Address of flash to do erase. * @param[in] uiLength Date length to be written. * @return None */ void Hv_Drv_Flash_OnlyErase(UINT32 uiReadAddr, UINT32 uiLength) { Hv_Vos_AcquireSemaphore(g_pstFlashSeamphone); Flash_WriteProtectDisable(uiReadAddr); Flash_OnlyErase(uiReadAddr, uiLength); Flash_WriteProtectEnable(); Hv_Vos_ReleaseSemaphore(g_pstFlashSeamphone); return; } /** * @brief Erase flash by a 64K Bytes(Multi Sector) length. Warning: Always erase 64K bytes, please be sure to keep your data safe. * @param[in] uiAddr Address of flash to do erase. * @return None */ void Hv_Drv_Flash_OnlyEraseMultiSector(UINT32 uiAddr) { Hv_Vos_AcquireSemaphore(g_pstFlashSeamphone); Flash_WriteProtectDisable(uiAddr); Flash_OnlyEraseMultiSector(uiAddr); Flash_WriteProtectEnable(); Hv_Vos_ReleaseSemaphore(g_pstFlashSeamphone); return; } /** * @brief Write flash. * @param[in] uiWriteAddr Address of flash to do write. * @param[in] pucWriteBuf Date buffer to be written. * @param[in] uiLength Date length to be written. * @return None */ Status Hv_Drv_Flash_OnlyWrite(UINT32 uiWriteAddr, UCHAR8* pucWriteBuf, UINT32 uiLength) { UINT32 uiPreIdx = 0; UINT32 uiPreDat = 0; Status uiRet = HV_SUCCESS; Hv_Vos_AcquireSemaphore(g_pstFlashSeamphone); Flash_WriteProtectDisable(uiWriteAddr); uiPreIdx = uiWriteAddr % PAGE_WRITE; HV_LOGV("Hv_Drv_Flash_OnlyWrite uiWriteAddr %x uiPreIdx %x, length %d\n", uiWriteAddr, uiPreIdx,uiLength); if (uiPreIdx) { uiPreDat = PAGE_WRITE - uiPreIdx; if (uiLength < uiPreDat) { uiPreDat = uiLength; } HV_MEMSET(g_ucReadBuf, 0xff, PAGE_READ); HV_MEMSET(g_ucWriteBuf, 0xff, PAGE_READ); Hv_Vos_InvalidAllDCache(); uiWriteAddr &= ~0xff; Flash_OnlyRead(uiWriteAddr, g_ucReadBuf, uiPreIdx); Hv_Vos_Memcpy(&g_ucReadBuf[uiPreIdx], pucWriteBuf, uiPreDat); uiRet = Flash_OnlyWrite(uiWriteAddr, g_ucReadBuf, PAGE_WRITE); uiLength = uiLength - uiPreDat; uiWriteAddr += PAGE_WRITE; pucWriteBuf += uiPreDat; } if ((uiLength > 0) && (uiRet == HV_SUCCESS)) { uiRet = Flash_OnlyWrite(uiWriteAddr, pucWriteBuf, uiLength); } Flash_WriteProtectEnable(); Hv_Vos_ReleaseSemaphore(g_pstFlashSeamphone); return uiRet; } /** * @brief Write flash. * @param[in] uiReadAddr Address of flash to do read. * @param[in] pucReadBuf Buffer for saving read back data. * @param[in] uiLength Date length to be read. * @return None */ void Hv_Drv_Flash_OnlyRead(UINT32 uiReadAddr, UCHAR8* pucReadBuf, UINT32 uiLength) { UINT32 uiPreIdx = 0; UINT32 uiPreDat = 0; Hv_Vos_AcquireSemaphore(g_pstFlashSeamphone); HV_MEMSET(g_ucReadBuf, 0xff, PAGE_READ); Hv_Vos_InvalidAllDCache(); uiPreIdx = uiReadAddr % PAGE_READ; HV_LOGV("Hv_Drv_Flash_OnlyRead uiReadAddr %x uiPreIdx %x, length %d\n", uiReadAddr, uiPreIdx,uiLength); if (uiPreIdx) { uiPreDat = PAGE_READ - uiPreIdx; uiReadAddr &= ~0xff; if (uiLength < uiPreDat) { uiPreDat = uiLength; } Flash_OnlyRead(uiReadAddr, g_ucReadBuf, PAGE_READ); Hv_Vos_Memcpy(pucReadBuf, g_ucReadBuf+uiPreIdx, uiPreDat); uiLength = uiLength - uiPreDat; uiReadAddr += PAGE_READ; pucReadBuf += uiPreDat; } if (uiLength > 0) { Flash_OnlyRead(uiReadAddr, pucReadBuf, uiLength); } Hv_Vos_ReleaseSemaphore(g_pstFlashSeamphone); return; } /** * @brief whether w/r is ongoing. * @return w/r state */ UCHAR8 Hv_Drv_Flash_InWritting(void) { Hv_Vos_AcquireSemaphore(g_pstFlashSeamphone); return 0; } /** * @brief Flash chip erase. * @param[in] None. * @return None */ void Hv_Drv_Flash_EraseChip(void) { Hv_Drv_Flash_ProtectDisable(); _Flash_Erase(g_pFlash, FLASH_ERASE_CHIP, 0); Flash_WriteProtectEnable(); }