📄 s3c2450_fil.c
字号:
///////////////////////////////////////////////////////////////
//
// MODULE : FIL
// NAME : S3C2450X Flash Interface Layer
// FILE : S3C2450_FIL.c
// PURPOSE :
//
///////////////////////////////////////////////////////////////
//
// COPYRIGHT 2003-2006 SAMSUNG ELECTRONICS CO., LTD.
// ALL RIGHTS RESERVED
//
// Permission is hereby granted to licensees of Samsung Electronics
// Co., Ltd. products to use or abstract this computer program for the
// sole purpose of implementing a product based on Samsung
// Electronics Co., Ltd. products. No other rights to reproduce, use,
// or disseminate this computer program, whether in part or in whole,
// are granted.
//
// Samsung Electronics Co., Ltd. makes no representation or warranties
// with respect to the performance of this computer program, and
// specifically disclaims any responsibility for any damages,
// special or consequential, connected with the use of this program.
//
///////////////////////////////////////////////////////////////
//
// REVISION HISTORY
//
// 2006.10.19 dodan2(gabjoo.lim@samsung.com)
// Draft Version
// 2007.03.25 ksk
// Support 4KByte/Page NAND Flash Device
//
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////
// Header File
///////////////////////////////////////////////
#include <WMRConfig.h>
#include <WMRTypes.h>
#include <OSLessWMROAM.h>
#include <FIL.h>
#include <string.h>
#include <S3C2450_FIL.h>
#include <s3c2450_dma.h>
#include <s3c2450_nand.h>
#include <s3c2450_matrix.h>
//#define USE_SETKMODE
#define USE_2CE_NAND
///////////////////////////////////////////////
// Transfer Mode
///////////////////////////////////////////////
#define ASM (0) // Assembly Code
#define DMA (1) // DMA Transfer
#define NAND_TRANS_MODE ASM
///////////////////////////////////////////////
// NAND DMA Buffer
///////////////////////////////////////////////
//#define NAND_DMA_BUFFER_UA (0xA0100000+0x25800) // LCD Frame Buffer
//#define NAND_DMA_BUFFER_PA (0x30100000+0x25800)
#define NAND_DMA_BUFFER_UA (0xB0700000) // Stepping Stone (Check Oemaddrtab_cgf.inc !!!!)
#define NAND_DMA_BUFFER_PA (0x40000000)
///////////////////////////////////////////////
// Debug Print Macro
///////////////////////////////////////////////
#define RETAILMSG(cond, printf_exp) ((cond)?(NKDbgPrintfW printf_exp),1:0)
#define NAND_ERR(x) RETAILMSG(TRUE, x)
//#define NAND_ERR(x)
//#define NAND_MSG(x) RETAILMSG(TRUE, x)
#define NAND_MSG(x)
#define NAND_LOG(x) RETAILMSG(TRUE, x)
//#define NAND_LOG(x)
///////////////////////////////////////////////
// Device type context definitions
///////////////////////////////////////////////
typedef struct
{
UINT8 nDevID; // Device ID
UINT8 nHidID; // Hidden ID
UINT32 nNumOfBlocks; // Number of Blocks
UINT32 nPagesPerBlock; // Pages per block
UINT32 nSectorsPerPage; // Sectors per page
BOOL32 b2XProgram; // 2 plane program
BOOL32 b2XRead; /* 2 plane read */
BOOL32 b2XReadStatus; /* 2 plane read status */
BOOL32 bDualDie; // internal interleaving
BOOL32 bMLC; // MLC
} DEVInfo;
PRIVATE const DEVInfo stDEVInfo[] = {
/*****************************************************************************/
/* Device ID */
/* Hidden ID */
/* Blocks */
/* Pages per block */
/* Sectors per page */
/* 2X program */
/* 2X read */
/* 2x status */
/* internal Interleaving */
/* MLC */
/*****************************************************************************/
#if (WMR_SLC_SUPPORT)
/* SLC NAND ID TABLE */
{0xF1, 0x80, 1024, 64, 4, FALSE32, FALSE32, FALSE32, FALSE32, FALSE32}, /* 1Gb SLC(K9F1G08) Mono */
{0xF1, 0x00, 1024, 64, 4, FALSE32, FALSE32, FALSE32, FALSE32, FALSE32}, /* 1Gb SLC(K9F1G08) Mono B-die */
{0xDA, 0x80, 2048, 64, 4, FALSE32, FALSE32, FALSE32, FALSE32, FALSE32}, /* 2Gb SLC(K9F2G08) Mono */
{0xDA, 0x10, 2048, 64, 4, TRUE32, FALSE32, FALSE32, FALSE32, FALSE32}, /* 2Gb SLC(K9F2G08) Mono A-die */
{0xDA, 0xC1, 2048, 64, 4, FALSE32, FALSE32, FALSE32, FALSE32, FALSE32}, /* 2Gb SLC(K9K2G08) DDP */
{0xDC, 0x10, 4096, 64, 4, TRUE32, FALSE32, FALSE32, FALSE32, FALSE32}, /* 4Gb SLC(K9F4G08) Mono */
{0xDC, 0xC1, 4096, 64, 4, FALSE32, FALSE32, FALSE32, TRUE32, FALSE32}, /* 4Gb SLC(K9K4G08) DDP */
{0xD3, 0x51, 8192, 64, 4, TRUE32, FALSE32, FALSE32, TRUE32, FALSE32}, /* 8Gb SLC(K9K8G08) DDP */
{0xD3, 0x10, 4096, 64, 8, TRUE32, TRUE32, TRUE32, FALSE32, FALSE32}, /* 8Gb SLC(K9F8G08) Mono */
#endif
#if (WMR_MLC_SUPPORT)
/* MLC NAND ID TABLE */
{0xDC, 0x14, 2048, 128, 4, TRUE32, FALSE32, FALSE32, FALSE32, TRUE32}, /* 4Gb MLC(K9G4G08) Mono */
{0xD3, 0x55, 4096, 128, 4, TRUE32, FALSE32, FALSE32, TRUE32, TRUE32}, /* 8Gb MLC(K9L8G08) DDP */
{0xD3, 0x14, 4096, 128, 4, TRUE32, FALSE32, FALSE32, FALSE32, TRUE32}, /* 8Gb MLC(K9G8G08) Mono */
{0xD5, 0x55, 8192, 128, 4, TRUE32, FALSE32, FALSE32, TRUE32, TRUE32}, /* 16Gb MLC(K9LAG08) DDP */
{0xD5, 0x14, 4096, 128, 8, TRUE32, TRUE32, TRUE32, FALSE32, TRUE32}, /* 16Gb MLC(K9GAG08) Mono */
{0xD7, 0x55, 8192, 128, 8, TRUE32, TRUE32, TRUE32, TRUE32, TRUE32}, /* 32Gb MLC(K9LBG08) DDP */
#endif
};
///////////////////////////////////////////////
// PRIVATE variables definitions
///////////////////////////////////////////////
PRIVATE BOOL32 bInternalInterleaving = FALSE32;
PRIVATE BOOL32 aNeedSync[WMR_MAX_DEVICE * 2];
PRIVATE volatile S3C2450_NAND_REG *pNANDFConReg = NULL;
PRIVATE volatile S3C2450_DMA_REG *pDMAConReg = NULL;
PRIVATE volatile S3C2450_MATRIX_REG *pMatrixConReg = NULL;
PRIVATE UINT8 aTempSBuf[NAND_SPAREPAGE_SIZE] =
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
///////////////////////////////////////////////
// Private Function Prototype
///////////////////////////////////////////////
PRIVATE INT32 Read_DeviceID(UINT32 nBank, UINT8 *pDID, UINT8 *pHID);
PRIVATE UINT32 Read_Sector(UINT32 nBank, UINT32 nPpn, UINT32 nSctOffset, UINT8* pBuf, pSECCCxt pSpareCxt, BOOL32 bCheckAllFF);
PRIVATE UINT32 Read_Spare(UINT32 nBank, UINT32 nPpn, pSECCCxt pSpareCxt);
PRIVATE VOID Write_Sector(UINT32 nPpn, UINT32 nSctOffset, UINT8* pBuf);
PRIVATE VOID Write_Spare(UINT32 nBank, UINT32 nPpn, pSECCCxt pSpareCxt);
PRIVATE UINT32 Decoding_MainECC(UINT8* pBuf);
PRIVATE UINT32 Decoding_SpareECC(UINT8* pBuf);
PRIVATE UINT32 _IsAllFF(UINT8* pBuf, UINT32 nSize);
PRIVATE UINT32 _TRDelay(UINT32 nNum);
PRIVATE UINT32 _TRDelay2(UINT32 nNum);
///////////////////////////////////////////////
// ECC Decoding Function Return Value
///////////////////////////////////////////////
#define ECC_CORRECTABLE_ERROR (0x1)
#define ECC_UNCORRECTABLE_ERROR (0x2)
#define ECC_ALL_FF (0x4)
//#define PAGE_CORRECTABLE_ERROR_MASK (0x11111) // for 2KByte/Page
//#define PAGE_UNCORRECTABLE_ERROR_MASK (0x22222) // for 2KByte/Page
#define PAGE_CORRECTABLE_ERROR_MASK (0x15555) // for 4KByte/Page
#define PAGE_UNCORRECTABLE_ERROR_MASK (0x2AAAA) // for 4KByte/Page
#define PAGE_ALL_FF_MASK (0x44444)
#define SPARE_ALL_FF_MASK (0x40000)
///////////////////////////////////////////////
// ECC Decoding Value for All FF
///////////////////////////////////////////////
#define ECCVAL_ALLFF (0xFFFFFFFF)
#if (NAND_TRANS_MODE == ASM)
extern void _Read_512Byte(UINT8* pBuf);
extern void _Read_512Byte_Unaligned(UINT8* pBuf);
extern void _Write_512Byte(UINT8* pBuf);
extern void _Write_512Byte_Unaligned(UINT8* pBuf);
extern void _Write_Dummy_468Byte_AllFF(void);
extern void _Write_Dummy_436Byte_AllFF(void);
#elif (NAND_TRANS_MODE == DMA)
PRIVATE VOID Read_512Byte_DMA(UINT8* pBuf);
PRIVATE VOID Write_512Byte_DMA(UINT8* pBuf);
PRIVATE VOID Write_Dummy_468Byte_AllFF_DMA(void);
#endif
///////////////////////////////////////////////
// Code Implementation
///////////////////////////////////////////////
/*****************************************************************************/
/* */
/* NAME */
/* NAND_Init */
/* DESCRIPTION */
/* This function inits NAND device. */
/* PARAMETERS */
/* None */
/* RETURN VALUES */
/* FIL_SUCCESS */
/* NAND_Init is success. */
/* FIL_CRITICAL_ERROR */
/* NAND_Init is failed. */
/* NOTES */
/* */
/*****************************************************************************/
INT32
NAND_Init(VOID)
{
UINT32 nDevIdx;
UINT32 nScanIdx = 0, nCompIdx = 0;
UINT8 nDevID, nHiddenID;
UINT32 nDevCnt = 0;
BOOL32 bComp = FALSE32;
NAND_MSG((_T("[FIL]++NAND_MLC_Init()\r\n")));
#if (BSP_TYPE == BSP_SMDK2443)
pNANDFConReg = (volatile S3C2450_NAND_REG *)0xB1400000; // 0x4E000000
pMatrixConReg = (volatile S3C2450_MATRIX_REG *)0xB1500000; // 0x4E800000
#elif (BSP_TYPE == BSP_SMDK2450)
pNANDFConReg = (volatile S3C2450_NAND_REG *)0xB1500000; // 0x4E000000
pMatrixConReg = (volatile S3C2450_MATRIX_REG *)0xB1600000; // 0x4E800000
#endif
pDMAConReg = (volatile S3C2450_DMA_REG *)0xB0E00000; // 0x4B000000
// Initialize NAND Flash Controller for SLC Large Block NAND Flash
pNANDFConReg->NFCONF = NF_1BIT_ECC | NF_TACLS(DEFAULT_TACLS) | NF_TWRPH0(DEFAULT_TWRPH0) | NF_TWRPH1(DEFAULT_TWRPH1);
pNANDFConReg->NFCONT = NF_MAIN_ECC_LOCK | NF_SPARE_ECC_LOCK | NF_INIT_MECC | NF_INIT_SECC | NF_NFCE1 | NF_NFCE0 | NF_NFCON_EN;
pNANDFConReg->NFSTAT = NF_RNB_READY; // Clear RnB Transition Detect Bit
// Initialize EBICON for 2nd nCE pin (nFCE1)
#ifdef USE_2CE_NAND
pMatrixConReg->EBICON |= (0x1<<8); // Bank1_Cfg -> NAND
#endif
/* Device's ID must be available and equal to each other */
for(nDevIdx = 0; nDevIdx < WMR_MAX_DEVICE; nDevIdx++)
{
nScanIdx = Read_DeviceID(nDevIdx, &nDevID, &nHiddenID);
if (nScanIdx == FIL_CRITICAL_ERROR)
{
nScanIdx = nCompIdx;
break;
}
if ((nCompIdx != nScanIdx) && (bComp))
{
return FIL_CRITICAL_ERROR;
}
nCompIdx = nScanIdx;
bComp = TRUE32;
nDevCnt++;
}
if(stDEVInfo[nScanIdx].bMLC)
{
SET_DevType(WMR_MLC);
}
else
{
SET_DevType(WMR_SLC);
}
if(stDEVInfo[nScanIdx].bDualDie && nDevCnt <= 2)
{
/* multi chip dual die (DDP) */
BLOCKS_PER_BANK = stDEVInfo[nScanIdx].nNumOfBlocks >> 1;
BANKS_TOTAL = nDevCnt * 2;
bInternalInterleaving = TRUE32;
}
else
{
BLOCKS_PER_BANK = stDEVInfo[nScanIdx].nNumOfBlocks;
BANKS_TOTAL = nDevCnt;
bInternalInterleaving = FALSE32;
}
SECTORS_PER_PAGE = stDEVInfo[nScanIdx].nSectorsPerPage;
TWO_PLANE_PROGRAM = stDEVInfo[nScanIdx].b2XProgram;
if (TWO_PLANE_PROGRAM == TRUE32)
{
BLOCKS_PER_BANK /= 2;
}
TWO_PLANE_READ = stDEVInfo[nScanIdx].b2XRead;
TWO_PLANE_READ_STATUS = stDEVInfo[nScanIdx].b2XReadStatus;
PAGES_PER_BLOCK = stDEVInfo[nScanIdx].nPagesPerBlock;
/* 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] 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_LOG((_T("[FIL] ##############################\r\n")));
NAND_LOG((_T("[INFO] IS_CHECK_SPARE_ECC = %d\n"), IS_CHECK_SPARE_ECC));
NAND_LOG((_T("[INFO] IS_SUPPORT_INTERNAL_INTERLEAVING = %d\n"), IS_SUPPORT_INTERNAL_INTERLEAVING));
NAND_LOG((_T("[INFO] PAGES_PER_BLOCK = %d\n"), PAGES_PER_BLOCK));
NAND_MSG((_T("[FIL]--NAND_Init()\r\n")));
return FIL_SUCCESS;
}
/*****************************************************************************/
/* */
/* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -