📄 tcl_gdi_flash_cfi.c
字号:
/* Write the last unaligned byte */
// TODO:need to think about endian
iData = ((*(pData+uStartOdd+i*2))<<8)|uEndOddData;
if ( !FL_WriteFlashWord( uWriteOfs+i, iData ) )
{
FLASH_ERROR(("3 - Flash write failed at offset %x\n",(uWriteOfs+i)));
/* Disable writes to the flash */
DisableFlash( );
return TCL_GDI_FLASH_WRITE_FAILURE;
}
}
}
else
{
for( i=0; i<uDataLen; i++ )
{
/* Write the word to the flash */
iData = pData[i];
if ( !FL_WriteFlashWord( uOffset+i, iData ) )
{
FLASH_ERROR(("1 - Flash write failed at offset %x\n",(uOffset+i)));
/* Disable writes to the flash */
DisableFlash( );
return TCL_GDI_FLASH_WRITE_FAILURE;
}
}
}
/* Disable writes to the flash */
DisableFlash( );
*pAlreadyWriteLen = i;
return TCL_NO_ERROR;
}
/******************************************************************************
* Function: FL_WriteFlashBuffer
* Description: This function burns at least one 16bit word and 32 at most.
* Calls: omit
* Called By: omit
* Table Accessed: none
* Table Updated: none
* Input: iOffset - where in the flash to burn the data, must be multiple of 32
usDataWord - the start address of data to be burn
DataCounter - total byte to written to flash.
* Output: none
* Return: TCL_TRUE - 成功
TCL_FALSE - 出错
*Arithmetic
* Others:
* Note:
* Author Date Purpose
*----------------------------------------------------------------------------
* JokQu 20080229 create
******************************************************************************/
TCL_BOOL FL_WriteFlashBuffer(TCL_INT32 iOffset, TCL_UCHAR *pucBuff, TCL_UINT8 DataCounter)
{
TCL_UINT8 iLoop = 0;
TCL_UINT32 SectorAdd = iOffset & 0xFFFF00;
if(0 != (iOffset & 0x1F))
{
return TCL_FALSE;
}
/* write first two unlock command */
FLASH_UnlockCmd();
/* write buffer load command */
WRITE_FLASH(SectorAdd,0x25);
/* write the number of location.*/
WRITE_FLASH(SectorAdd,DataCounter-1);
/* write the first address and data pair */
WRITE_FLASH(iOffset,pucBuff[0]);
for(iLoop = 1; iLoop < DataCounter; iLoop++)
{
/* write the left address and data pairs */
WRITE_FLASH(iOffset+iLoop,pucBuff[iLoop]);
}
/* write the program buffer to flash command */
WRITE_FLASH(SectorAdd,0x29);
return FLASH_CompletionPolling(iOffset+DataCounter-1, pucBuff[DataCounter-1]);
}
/******************************************************************************
* Function: CFI_FastWrite
* Description: 快速写flash
* Calls: omit
* Called By: omit
* Table Accessed: none
* Table Updated: none
* Input: TCL_UINT32 uOffset - 地址
TCL_UINT8 *pData - 数据buffer
TCL_UINT32 uDataLen - 要写的数据长度
* Output: TCL_UINT32 *pAlreadyReadLen - 实际写成功的数据长度
* Return: ReturnType ( reference define of ReturnType)
*Arithmetic
* Others:
* Note:
* Author Date Purpose
*----------------------------------------------------------------------------
* JokQu 20080229 create
******************************************************************************/
TCL_UINT32 CFI_FastWrite(TCL_UINT32 uOffset, TCL_UINT8 *pData, TCL_UINT32 uDataLen,TCL_UINT32 *pAlreadyWriteLen)
{
TCL_INT32 i, iData;
TCL_UINT8 uMirrorBit;
TCL_UINT8 uFlashSize;
/* Enable writes to the flash */
EnableFlash( );
uFlashSize = READ_FLASH(CFI_DEV_SIZE_ADDR);
WRITE_FLASH(CMD_CFI_QUERY_ADDR[gIsSst16Bit], CMD_CFI_QUERY_DATA);
uMirrorBit = 0x08 & READ_FLASH(CMD_CFI_PROTECH_ADDR);
WRITE_FLASH(CMD_RESET_ADDR[gIsSst16Bit], CMD_RESET_DATA[gIsSst16Bit]);
/* For each word in the image */
if(uMirrorBit & (uFlashSize > 0x15))
{
for( i=0; i<(TCL_INT32)uDataLen; )
{
if(0 == ((uOffset+i) & 0x1F))
{
if(TCL_FALSE == FL_WriteFlashBuffer(uOffset+i,pData+i,((uDataLen-i)>32)?32:(uDataLen-i)))
{
FLASH_ERROR(("Flash write buffer failed at offset %x\n",(uOffset+i)));
DisableFlash();
return TCL_GDI_FLASH_WRITE_FAILURE;
}
i+=32;
}
else
{
iData = pData[i];
if ( !FL_WriteFlashWord( uOffset+i, iData ) )
{
FLASH_ERROR(("Flash write failed at offset %x\n",(uOffset+i)));
DisableFlash( );
return TCL_GDI_FLASH_WRITE_FAILURE;
}
i+=1;
}
}
}
else
{
for( i=0; i<(TCL_INT32)uDataLen; )
{
iData = pData[i];
if ( !FL_WriteFlashWord( uOffset+i, iData ) )
{
FLASH_ERROR(("Flash write failed at offset %x\n",(uOffset+i)));
DisableFlash( );
return TCL_GDI_FLASH_WRITE_FAILURE;
}
i+=1;
}
}
/* Disable writes to the flash */
DisableFlash( );
*pAlreadyWriteLen = i;
return TCL_NO_ERROR;
}
/******************************************************************************
* Function: CFI_ReadFlash
* Description: 读flash
* Calls: omit
* Called By: omit
* Table Accessed: none
* Table Updated: none
* Input: TCL_UINT32 uOffset - 地址
TCL_UINT8 *pData - 数据buffer
TCL_UINT32 uDataLen - 要读取的数据长度
* Output: TCL_UINT32 *pAlreadyReadLen - 实际读取的数据长度
* Return: ReturnType ( reference define of ReturnType)
*Arithmetic
* Others:
* Note:
* Author Date Purpose
*----------------------------------------------------------------------------
* JokQu 20080229 create
******************************************************************************/
TCL_UINT32 CFI_ReadFlash(TCL_UINT32 uOffset, TCL_UINT8 *pData, TCL_UINT32 uDataLen,TCL_UINT32 *pAlreadyReadLen)
{
TCL_UINT32 i;
TCL_UINT8 OddOffset;
TCL_UINT8 OddCnt;
TCL_UINT16 word;
TCL_UINT32 Index;
if (WorkMode == WORK_MODE_16BIT)
{
Index = 0;
OddOffset = uOffset % 2;
uOffset = uOffset / 2;
OddCnt = (uDataLen - OddOffset) % 2;
/* Check if the offset is odd. */
if (OddOffset)
{
word = *((TCL_UINT16*)FLASH_ADDRESS(uOffset));
pData[Index++] = (TCL_UINT8)word;
}
for( i=0; i < (uDataLen - OddOffset) / 2; i++ )
{
word = *((TCL_UINT16*)FLASH_ADDRESS(uOffset + i + OddOffset));
pData[Index++] = (TCL_UINT8)(word >> 8);
pData[Index++] = (TCL_UINT8)word;
}
if (OddCnt)
{
word = *((TCL_UINT16*)FLASH_ADDRESS((uOffset + i + OddOffset)));
pData[Index++] = (TCL_UINT8)(word >> 8);
}
}
else
{
for( i=0; i < uDataLen; i++ )
{
pData[i] = *((TCL_UINT8*)(FLASH_BASE_ADDR + uOffset + i));
}
}
*pAlreadyReadLen = uDataLen;
return TCL_NO_ERROR;
}
/******************************************************************************
* Function: CFI_EraseSectors
* Description: 擦除扇区
* Calls: omit
* Called By: omit
* Table Accessed: none
* Table Updated: none
* Input: TCL_UINT32 uStartSectorNum - 起始扇区
TCL_UINT32 uNumOfSecs - 要擦除的扇区数目
* Output: none
* Return: TCL_NO_ERROR - 操作成功
其它- 出错
* Others:
* Note:
* Author Date Purpose
*----------------------------------------------------------------------------
* JokQu 20080229 create
******************************************************************************/
TCL_UINT32 CFI_EraseSectors(TCL_UINT32 uStartSectorNum, TCL_UINT32 uNumOfSecs)
{
TCL_UINT32 i;
TCL_UINT32 addr;
TCL_BOOL bStatus = TCL_FALSE;
/* erase the whole flash */
if(uNumOfSecs == 0xFFFFFFFF)
{
FLASH_DEBUG(("....................................\n"));
FLASH_DEBUG(("Warning: erase whole flash!\n"));
FLASH_DEBUG(("....................................\n"));
}
/* Enable writes to the flash */
EnableFlash();
/*--------------------------------------------------
We now load the sector erase buffer of the flash IC.
It will collect all the sectors addresess to be erased.
Erasure will start 50usec after the last address was added.
--------------------------------------------------*/
for( i=uStartSectorNum; i<uStartSectorNum + uNumOfSecs; i++ )
{
/* Issue unlock command */
FLASH_UnlockCmd();
/* Issue setup command */
WRITE_FLASH( CMD_SETUP_ADDR[gIsSst16Bit] / WorkMode, CMD_SETUP_DATA[gIsSst16Bit]);
/* Issue 2 additional unlock cycles */
FLASH_UnlockCmd();
/* Issue setup command */
addr = CFI_FlashSecStartAddr( i ) / WorkMode;
WRITE_FLASH( addr, mEraseCmd );
FLASH_DEBUG(("CFI_EraseFlash: sector = %d, address = %x\n",
i,FLASH_BASE_ADDR+CFI_FlashSecStartAddr( i ) / WorkMode));
/* Wait until programming completes */
bStatus = FLASH_CompletionPolling( addr, FLASH_DQ7 );
}
/* Disable writes to the flash */
DisableFlash();
if ( TCL_TRUE == bStatus )
{
return TCL_NO_ERROR;
}
else
{
return TCL_GDI_FLASH_ERASE_FAILURE;
}
}
/******************************************************************************
* Function: FlashProbeCFI
* Description: 获取CFI 信息
* Calls: omit
* Called By: omit
* Table Accessed: none
* Table Updated: none
* Input: TCL_GDI_FLASH_INFO *pFlashInfo - Flash 信息指针
* Output: TCL_GDI_FLASH_INFO *pFlashInfo - Flash 信息
* Return: TCL_NO_ERROR
* Others:
* Note:
* Author Date Purpose
*----------------------------------------------------------------------------
* JokQu 20080229 create
******************************************************************************/
static TCL_BOOL FlashProbeCFI(TCL_GDI_FLASH_INFO *pFlashInfo)
{
TCL_UINT8 gNumEraseRegions;
TCL_UINT8 i;
TCL_UINT8 j;
TCL_UINT32 gFlashTotalSize;
TCL_UINT32 size;
FL_ERASE_REGION_INFO gEraseRegionInfo;
TCL_UINT16 puSectorNum = 0;
FLASH_DEBUG(("FlashProbeCFI: enter\n"));
/* Enable writes to the flash */
EnableFlash( );
if (gIsSst16Bit)
{
FLASH_UnlockCmd();
}
/* Issue CFI Query command */
WRITE_FLASH(CMD_CFI_QUERY_ADDR[gIsSst16Bit] / WorkMode, CMD_CFI_QUERY_DATA);
/* test if CFI supported */
if( ('Q'!=READ_FLASH(CFI_DEV_QRY_ADDR / WorkMode)) ||
('R'!=READ_FLASH((CFI_DEV_QRY_ADDR+2) / WorkMode)) ||
('Y'!=READ_FLASH((CFI_DEV_QRY_ADDR+4) / WorkMode)) )
{
pFlashInfo->uCFI = 0;
FLASH_DEBUG(("Not Support CFI\n"));
return TCL_FALSE;
}
pFlashInfo->uCFI = 1;
FLASH_DEBUG(("Support CFI\n"));
/*-------------------------------------------------------
Get device boot type.
For some special type, we can not get boot type from CFI
In this case, we should have got boot type from Device ID.
------------------------------------------------------- */
if( 0xFF == pFlashInfo->eBootMode)
{
TCL_UINT8 bootType;
TCL_UINT16 pri_adr;
pri_adr = (READ_FLASH(CFI_PRIMARY_ADDR1 / WorkMode)|(READ_FLASH(CFI_PRIMARY_ADDR2 / WorkMode)<<8)) << 1;
bootType = READ_FLASH((pri_adr + 0x1E) / WorkMode);
FLASH_DEBUG(("CFI pri_adr: 0x%x. bootType %d\n", pri_adr, bootType));
if ((bootType != 2) && (bootType != 3))
{
FLASH_DEBUG(("CFI does not contain boot bank location. Assuming Bottom boot.\n"));
bootType = 2;
}
if(bootType == 3)
{
pFlashInfo->eBootMode= TCL_GDI_FLBOOT_TOP;
}
else
{
pFlashInfo->eBootMode = TCL_GDI_FLBOOT_BOTTOM;
}
}
/* Read device size */
gFlashTotalSize = (1<<READ_FLASH(CFI_DEV_SIZE_ADDR / WorkMode));
/* Read ERASE REGIONS information */
gNumEraseRegions = READ_FLASH( CFI_NUM_ERASE_REGIONS_ADDR / WorkMode );
FLASH_DEBUG(("Flash Size: %dMB <%d erase regions>\n", gFlashTotalSize>>20, gNumEraseRegions));
/* init total sector number */
pFlashInfo->uFlashSize = gFlashTotalSize;
puSectorNum = 0;
size = 0;
j = 0;
for(i=0; i<gNumEraseRegions; i++)
{
TCL_UINT32 uCurPos;
if((pFlashInfo->eBootMode) == TCL_GDI_FLBOOT_TOP)
{
/* top boot mode flash */
uCurPos = gNumEraseRegions - i - 1;
}
else
{
/* bottom boot mode flash */
uCurPos = i;
}
gEraseRegionInfo.numSectors =
READ_FLASH((CFI_ERASE_REGION_START_ADDR+8*uCurPos) / WorkMode)
+ (READ_FLASH((CFI_ERASE_REGION_START_ADDR+8*uCurPos+2) / WorkMode)<<8) + 1;
gEraseRegionInfo.sectorSize =
(READ_FLASH((CFI_ERASE_REGION_START_ADDR+8*uCurPos+4) / WorkMode)<<8)
+ (READ_FLASH((CFI_ERASE_REGION_START_ADDR+8*uCurPos+6) / WorkMode)<<16);
for(j=0;j<gEraseRegionInfo.numSectors;j++)
{
pFlashInfo->eSectorInfo[puSectorNum].uSectorNo = puSectorNum;
pFlashInfo->eSectorInfo[puSectorNum].uStartAdress = size;
pFlashInfo->eSectorInfo[puSectorNum].uSecLength = gEraseRegionInfo.sectorSize;
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -