?? s3c6410_fil.c
字號:
// If FS_SCAN_RATIO value is 0, skip Scan.
// OS_SCAN_RATIO means scan percentage of Total SPECIAL AREA size.
// If OS_SCAN_RATIO value is 0, skip Scan.
OS_SCAN_RATIO = 10; // 10 means (100/10)% => 10%
if ( stDEVInfo[nScanIdx].nNumOfBlocks <= 1024 )
{
FS_SCAN_RATIO = 20; // 10 means (100/10)% => 10%
}
else if ( stDEVInfo[nScanIdx].nNumOfBlocks <= 2048 )
{
FS_SCAN_RATIO = 50; // 20 means (100/20)% => 5%
}
else if ( stDEVInfo[nScanIdx].nNumOfBlocks <= 4096 )
{
FS_SCAN_RATIO = 100; // 50 means (100/50)% => 2%
}
else if ( stDEVInfo[nScanIdx].nNumOfBlocks <= 8192 )
{
FS_SCAN_RATIO = 200; // 100 means (100/100)% => 1%
}
else
{
FS_SCAN_RATIO = 400; // 200 means (100/200)% => 0.5%
}
// CRITICAL_READ_CNT value is used to avoid read disturbance problem.
// This value is critical count value to determine the count of read for reclaim.
// Every block have each read count value, this value is reset to 0 when boot up the system.
// If each block is read more than CRITICAL_READ_CNT value after boot up, this block is enter to reclaim list.
// This value is useful if the system is running long times without reboot.
// But system have to calls FTL_Reclaim function during running the system.
// If this CRITICAL_READ_CNT value is set to 0. It doesn't support Reclaim function using read count value.
// If you support periodic scan and reclaim by OnDisk or other application, you don't need to use this function.
CRITICAL_READ_CNT = 0;
// This flag determin the scan function during boot up.
BOOTING_SCAN = FALSE32;
/* DDP */
if (bInternalInterleaving)
{
for (nDevIdx = 0; nDevIdx < nDevCnt; nDevIdx++)
{
aNeedSync[nDevIdx * 2] = FALSE32;
aNeedSync[nDevIdx * 2 + 1] = FALSE32;
}
}
#if (WMR_MLC_LSB_RECOVERY)
MLC_LSB_CLASS = GetMlcClass( stDEVInfo[nScanIdx].nDevID,
stDEVInfo[nScanIdx].nHidID);
#endif
CalcGlobal(bInternalInterleaving);
NAND_LOG((_T("[FIL] ##############################\r\n")));
NAND_LOG((_T("[FIL] FIL Global Information\r\n")));
NAND_LOG((_T("[FIL] BANKS_TOTAL = %d\r\n"), BANKS_TOTAL));
NAND_LOG((_T("[FIL] BLOCKS_PER_BANK = %d\r\n"), BLOCKS_PER_BANK));
NAND_LOG((_T("[FIL] TWO_PLANE_PROGRAM = %d\r\n"), TWO_PLANE_PROGRAM));
NAND_LOG((_T("[FIL] SUPPORT_INTERLEAVING = %d\r\n"), IS_SUPPORT_INTERLEAVING));
NAND_LOG((_T("[FIL] SUBLKS_TOTAL = %d\r\n"), SUBLKS_TOTAL));
NAND_LOG((_T("[FIL] PAGES_PER_SUBLK = %d\r\n"), PAGES_PER_SUBLK));
NAND_LOG((_T("[FIL] PAGES_PER_BANK = %d\r\n"), PAGES_PER_BANK));
NAND_LOG((_T("[FIL] SECTORS_PER_PAGE = %d\r\n"), SECTORS_PER_PAGE));
NAND_LOG((_T("[FIL] SECTORS_PER_SUPAGE = %d\r\n"), SECTORS_PER_SUPAGE));
NAND_LOG((_T("[FIL] SECTORS_PER_SUBLK = %d\r\n"), SECTORS_PER_SUBLK));
NAND_LOG((_T("[FIL] BYTES_PER_MAIN_PAGE = %d\r\n"), BYTES_PER_MAIN_PAGE));
NAND_LOG((_T("[FIL] USER_SECTORS_TOTAL = %d\r\n"), USER_SECTORS_TOTAL));
NAND_LOG((_T("[FIL] ADDRESS_CYCLE = %d\r\n"), DEV_ADDR_CYCLE));
NAND_LOG((_T("[FIL] ##############################\r\n\r\n")));
NAND_LOG((_T("[INFO] WMR_AREA_SIZE = %d\n"), WMR_AREA_SIZE));
NAND_LOG((_T("[INFO] SPECIAL_AREA_START = %d\n"), SPECIAL_AREA_START));
NAND_LOG((_T("[INFO] SPECIAL_AREA_SIZE = %d\n"), SPECIAL_AREA_SIZE));
NAND_LOG((_T("[INFO] VFL_AREA_START = %d\n"), VFL_AREA_START));
NAND_LOG((_T("[INFO] VFL_AREA_SIZE = %d\n"), VFL_AREA_SIZE));
NAND_LOG((_T("[INFO] VFL_INFO_SECTION_START = %d\n"), VFL_INFO_SECTION_START));
NAND_LOG((_T("[INFO] VFL_INFO_SECTION_SIZE = %d\n"), VFL_INFO_SECTION_SIZE));
NAND_LOG((_T("[INFO] RESERVED_SECTION_START = %d\n"), RESERVED_SECTION_START));
NAND_LOG((_T("[INFO] RESERVED_SECTION_SIZE = %d\n"), RESERVED_SECTION_SIZE));
NAND_LOG((_T("[INFO] FTL_INFO_SECTION_START = %d\n"), FTL_INFO_SECTION_START));
NAND_LOG((_T("[INFO] FTL_INFO_SECTION_SIZE = %d\n"), FTL_INFO_SECTION_SIZE));
NAND_LOG((_T("[INFO] LOG_SECTION_SIZE = %d\n"), LOG_SECTION_SIZE));
NAND_LOG((_T("[INFO] FREE_SECTION_START = %d\n"), FREE_SECTION_START));
NAND_LOG((_T("[INFO] FREE_SECTION_SIZE = %d\n"), FREE_SECTION_SIZE));
NAND_LOG((_T("[INFO] FREE_LIST_SIZE = %d\n"), FREE_LIST_SIZE));
NAND_LOG((_T("[INFO] DATA_SECTION_START = %d\n"), DATA_SECTION_START));
NAND_LOG((_T("[INFO] DATA_SECTION_SIZE = %d\n"), DATA_SECTION_SIZE));
NAND_LOG((_T("[INFO] FTL_AREA_START = %d\n"), FTL_AREA_START));
NAND_LOG((_T("[INFO] FTL_AREA_SIZE = %d\n"), FTL_AREA_SIZE));
NAND_MSG((_T("[FIL]--NAND_Init()\r\n")));
return FIL_SUCCESS;
}
/*****************************************************************************/
/* */
/* NAME */
/* NAND_GetPlatformInfo */
/* DESCRIPTION */
/* This function returns platform information */
/* PARAMETERS */
/* pstFILPlantformInfo */
/* Platform information */
/* RETURN VALUES */
/*****************************************************************************/
VOID
NAND_GetPlatformInfo(FILPlatformInfo* pstFILPlatformInfo)
{
NAND_LOG((_T("[INFO] ++NAND_GetPlatformInfo\n")));
/* Warning : Do not change !!!! */
pstFILPlatformInfo->nType = 1;
/* Address of command register in MAP11 */
pstFILPlatformInfo->nAddrOfCmdReg = 0xB0200008;
/* Address of address register */
pstFILPlatformInfo->nAddrOfAdrReg = 0xB020000C;
/* Address of register for reading ID*/
pstFILPlatformInfo->nAddrOfReadIDReg = 0xB0200010;
/* Address of status register */
pstFILPlatformInfo->nAddrOfStatusReg = 0xB0200028;
/* Command of reading Device ID */
pstFILPlatformInfo->nCmdOfReadID = CMD_READ_ID;
/* Command of read page */
pstFILPlatformInfo->nCmdOfReadPage = CMD_READ;
/* Command of read status */
pstFILPlatformInfo->nCmdOfReadStatus = CMD_READ_STATUS;
/* Mask value for Ready or Busy status */
pstFILPlatformInfo->nMaskOfRnB = NF_RNB_READY;
// Must be set CE to low
NF_CE_L(0);
NF_WAIT_RnB(0);
NAND_LOG((_T("[INFO] --NAND_GetPlatformInfo\n")));
return;
}
INT32
NAND_Read_Retry(UINT32 nBank, UINT32 nPpn, UINT32 nSctBitmap, UINT32 nPlaneBitmap,
UINT8* pDBuf, UINT8* pSBuf, BOOL32 bECCIn, BOOL32 bCleanCheck)
{
INT32 dwRet;
INT32 dwCnt;
dwRet = NAND_Read( nBank, nPpn, nSctBitmap, nPlaneBitmap, pDBuf, pSBuf, bECCIn, bCleanCheck);
if (bECCEngineError == TRUE32)
{
goto ECCPROBLEM;
}
// Try read again.
for ( dwCnt = 0; dwCnt < 10; dwCnt++ )
{
if ( dwRet == FIL_U_ECC_ERROR )
{
NAND_LOG((_T("[FIL] NAND_Read Try to read again(%d)\n"), dwCnt));
bReadSafeMode = TRUE32;
dwRet = NAND_Read( nBank, nPpn, nSctBitmap, nPlaneBitmap, pDBuf, pSBuf, bECCIn, bCleanCheck);
bReadSafeMode = FALSE32;
if (bECCEngineError == TRUE32)
{
goto ECCPROBLEM;
}
}
else
{
break;
}
}
return dwRet;
ECCPROBLEM:
{
nSctBitmap &= FULL_SECTOR_BITMAP_PAGE;
if ( pDBuf != NULL )
{
if ((nSctBitmap & LEFT_SECTOR_BITMAP_PAGE) > 0 && (nSctBitmap & RIGHT_SECTOR_BITMAP_PAGE) > 0)
{
WMR_MEMSET(pDBuf, 0x0, BYTES_PER_MAIN_PAGE);
WMR_MEMSET(pDBuf + BYTES_PER_MAIN_PAGE, 0x0, BYTES_PER_MAIN_PAGE);
}
else if ((nSctBitmap & LEFT_SECTOR_BITMAP_PAGE) > 0 && (nSctBitmap & RIGHT_SECTOR_BITMAP_PAGE) == 0)
{
WMR_MEMSET(pDBuf, 0x0, BYTES_PER_MAIN_PAGE);
}
else if ((nSctBitmap & LEFT_SECTOR_BITMAP_PAGE) == 0 && (nSctBitmap & RIGHT_SECTOR_BITMAP_PAGE) > 0)
{
WMR_MEMSET(pDBuf + BYTES_PER_MAIN_PAGE, 0x0, BYTES_PER_MAIN_PAGE);
}
}
NAND_ERR((_T("[FIL] NAND_Write(0x%x)\n"), nPpn));
NAND_Write( nBank, nPpn, nSctBitmap, nPlaneBitmap, pDBuf, pSBuf );
// TODO:
// Reset Device.
// HCLK_IROM, HCLK_MEM1, HCLK_MEM0, HCLK_MFC Should be Always On for power Mode (Something coupled with BUS operation)
pSYSConReg->HCLK_GATE |= ((1<<25)|(1<<22)|(1<<21)|(1<<0));
#if 0
_OEMSWReset();
#else
pWTDogReg->WTCON = WTCON_PRESCALE(WD_PRESCALER) | WTCON_CLK_DIV128 | WTCON_RESET;
pWTDogReg->WTDAT = WTDAT_CNT(0x1);
pWTDogReg->WTCNT = WTCNT_CNT(0x1);
pWTDogReg->WTCON |= WTCON_ENABLE;
#endif
while(1);
}
}
/*****************************************************************************/
/* */
/* NAME */
/* NAND_Read */
/* DESCRIPTION */
/* This function reads NAND page area */
/* PARAMETERS */
/* nBank [IN] Physical device number */
/* nPpn [IN] Physical page number */
/* nSctBitmap [IN] Physical sector bitmap in a page area */
/* nPlaneBitmap[IN] The indicator of the plane */
/* pDBuf [OUT] Buffer pointer of main area to read */
/* pSBuf [OUT] Buffer pointer of spare area to read */
/* bECCIn [IN] Whether read page with ECC value or not */
/* bCleanCheck [IN] When it's TRUE, checks the clean status */
/* of the page if the data of spare area is all */
/* 0xFF, returns PAGE_CLEAN */
/* RETURN VALUES */
/* FIL_SUCCESS */
/* NAND_Read is success. */
/* FIL_SUCCESS_CLEAN */
/* NAND_Read is success and all data is 0xFF. */
/* FIL_U_ECC_ERROR */
/* ECC value is not correct. */
/* NOTES */
/* */
/*****************************************************************************/
INT32
NAND_Read(UINT32 nBank, UINT32 nPpn, UINT32 nSctBitmap, UINT32 nPlaneBitmap,
UINT8* pDBuf, UINT8* pSBuf, BOOL32 bECCIn, BOOL32 bCleanCheck)
{
UINT32 nPbn;
UINT32 nPOffset;
UINT32 nPageReadStatus = 0;
UINT32 nPageReadStatus1st = 0;
UINT32 nPageReadStatus2nd = 0;
UINT32 nCnt;
UINT32 nRet = 0;
BOOL32 bECCErr = FALSE32;
BOOL32 bPageClean = TRUE32; // When the data is all 0xFF, regard the page as clean
BOOL32 bIsSBufNull = FALSE32; // When the pSBuf is NULL, set to check whether the page is clean or not
BOOL32 bSecondRead = FALSE32; // In case of twice read
BOOL32 bLoopNeed = FALSE32; // Only for nSctOffset == 8
BOOL32 bRetry = TRUE32;
UINT32 nLoopCount;
UINT32 nVBank;
UINT32 nPairBank;
UINT32 nSyncRet;
#ifdef USE_SETKMODE
BOOL bLastMode;
#endif
NAND_MSG((_T("[FIL]++NAND_Read(%d, %d, 0x%02x, 0x%02x, %d)\r\n"), nBank, nPpn, nSctBitmap, nPlaneBitmap, bCleanCheck));
// NAND_ERR((_T("[FIL]++NAND_Read(%d, %d, 0x%02x, 0x%02x, %d)\r\n"), nBank, nPpn, nSctBitmap, nPlaneBitmap, bCleanCheck)); // ksk dbg
// pDBuf & pSBuf can't be the NULL at the same time
if (nBank >= BANKS_TOTAL || nPpn >= PAGES_PER_BANK || (pDBuf == NULL && pSBuf == NULL))
{
NAND_ERR((_T("[FIL:ERR]--NAND_Read() : Parameter overflow\r\n")));
WMR_ASSERT(FALSE32);
return FIL_CRITICAL_ERROR;
}
WMR_ASSERT((nPlaneBitmap == enuBOTH_PLANE_BITMAP) || (nPlaneBitmap == enuLEFT_PLANE_BITMAP)
|| (nPlaneBitmap == enuRIGHT_PLANE_BITMAP) || (nPlaneBitmap == enuNONE_PLANE_BITMAP));
nVBank = nBank; // Do not change nBank before copy to nVBank
// avoid r/b check error with internal interleaving
if (bInternalInterleaving == TRUE32)
{
nPairBank = ((nBank & 0x1) == 1) ? (nBank - 1) : (nBank + 1);
}
/*
In case of Internal Interleaving, the first address of the second bank should be
the half of toal block number of NAND.
For example, In 4Gbit DDP NAND, its total block number is 4096.
So, the bank 0 has 2048 blocks (Physical number : 0 ~ 2047),
the bank 1 has another 2048 blocks (Physical number : 2048 ~ 4095).
therefore, first block address of Bank 1 could be the physically 2048th block.
*/
if (bInternalInterleaving == TRUE32)
{
if ((nBank & 0x1) == 1)
{
nPpn += PAGES_PER_BANK;
}
nBank /= 2;
}
nSctBitmap &= FULL_SECTOR_BITMAP_PAGE;
#if (WMR_STDLIB_SUPPORT)
nPbn = nPpn / PAGES_PER_BLOCK;
nPOffset = nPpn % PAGES_PER_BLOCK;
#else
nPbn = DIV(nPpn, PAGES_PER_BLOCK_SHIFT);
nPOffset = REM(nPpn, PAGES_PER_BLOCK_SHIFT);
#endif
// In case of 2 Plane Program, re-calculate the page address
if (TWO_PLANE_PROGRAM == TRUE32)
{
nPpn = nPbn * 2 * PAGES_PER_BLOCK + nPOffset;
if (nPlaneBitmap == enuBOTH_PLANE_BITMAP)
{
if(pDBuf != NULL)
{
if ((nSctBitmap & LEFT_SECTOR_BITMAP_PAGE) > 0 && (nSctBitmap & RIGHT_SECTOR_BITMAP_PAGE) > 0)
{
// read from both plane
bLoopNeed = TRUE32;
}
else if ((nSctBitmap & LEFT_SECTOR_BITMAP_PAGE) > 0 && (nSctBitmap & RIGHT_SECTOR_BITMAP_PAGE) == 0)
{
// read from left plane
bLoopNeed = FALSE32;
}
else if ((nSctBitmap & LEFT_SECTOR_BITMAP_PAGE) == 0 && (nSctBitmap & RIGHT_SECTOR_BITMAP_PAGE) > 0)
{
// read from right plane
bLoopNeed = FALSE32;
bSecondRead = TRUE32;
}
}
else
{
// When read only the spare area, must read twice
bLoopNeed = TRUE32;
}
}
else if (nPlaneBitmap == enuRIGHT_PLANE_BITMAP)
{
nPpn += PAGES_PER_BLOCK;
}
}
nLoopCount = SECTORS_PER_PAGE;
NAND_Sync(nVBank, &nSyncRet);
if (bInternalInterleaving == TRUE32)
{
// avoid r/b check error with internal interleaving
aNeedSync[nVBank] = FALSE32;
}
_B_SecondRead: // back here again for read right plane
if(bSecondRead)
{
nPpn += PAGES_PER_BLOCK;
nSctBitmap = (nSctBitmap >> SECTORS_PER_PAGE);
if(pDBuf != NULL)
{
pDBuf += BYTES_PER_MAIN_PAGE;
}
else
{
// When read only the spare, read 64 + 64 bytes to check the Bad Block
pSBuf += BYTES_PER_SPARE_PAGE;
}
}
#if (WMR_READ_RECLAIM)
READ_ERR_FLAG = FALSE32;
#endif
if(pSBuf == NULL)
{
pSBuf = aTempSBuf;
bIsSBufNull = TRUE32;
}
//NAND_Sync(nVBank, &nSyncRet);
#ifdef USE_SETKMODE
bLastMode = SetKMode(TRUE);
#endif
// Chip Select
NF_CE_L(nBank);
// Read Command (Always read spare area before main area in a page
NF_CMD(CMD_READ);
if (ECC_8BIT_SPPORT == FALSE32 && SECTORS_PER_PAGE == 8)
{
NF_SET_ADDR(nPpn, BYTES_PER_MAIN_PAGE+NAND_SECC_OFFSET_4K);
}
else
{
NF_SET_ADDR(nPpn, BYTES_PER_MAIN_PAGE);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -