⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c6410_fil.c

📁 6410BSP3
💻 C
📖 第 1 页 / 共 5 页
字号:
	// 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -