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

📄 s3c6410_fil.c

📁 6410BSP3
💻 C
📖 第 1 页 / 共 5 页
字号:
///////////////////////////////////////////////////////////////
//
//	MODULE		: FIL
//	NAME		: S3C6410X Flash Interface Layer
//	FILE			: S3C6410_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 <windows.h>
#include <WMRConfig.h>
#include <WMRTypes.h>
#include <OSLessWMROAM.h>
#include <FIL.h>
#include <string.h>
#include "S3C6410_FIL.h"
#include "S3C6410.h"
//#include "s3c6410_dma.h"
//#include "s3c6410_nand.h"
//#include "s3c6410_syscon.h"
//#include "s3c6410_matrix.h"

//#define USE_SETKMODE
#define USE_2CE_NAND

///////////////////////////////////////////////
// Transfer Mode
///////////////////////////////////////////////
#define ASM					(0)		// Assembly Code
#define DMA					(1)		// DMA Transfer

///////////////////////////////////////////////
// NAND DMA Buffer
///////////////////////////////////////////////
//#define NAND_DMA_BUFFER_UA	(0xA0100000+0x25800)		// LCD Frame Buffer
//#define NAND_DMA_BUFFER_PA	(0x30100000+0x25800)
#ifdef USING_DMA
#define NAND_DMA_BUFFER_UA	(0xB0700000)		// Stepping Stone (Check Oemaddrtab_cgf.inc !!!!)
#define NAND_DMA_BUFFER_PA	(0x40000000)
#endif
///////////////////////////////////////////////
// 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
	BOOL32  b8BitECC;	
} DEVInfo;

typedef struct
{
	UINT32	n8MECC0;				// 8MECC0
	UINT32	n8MECC1;				// 8MECC1
	UINT32	n8MECC2;				// 8MECC2
	UINT8	n8MECC3;				// 8MECC3
} MECC8;


typedef struct
{
	UINT8	nBadBlock;				// bad block marker;
	MECC8	t8MECC[8];				// 8MECC0 ~ 8
} SECCInfo;


PRIVATE const DEVInfo stDEVInfo[] = {
		/*****************************************************************************/
		/* Device ID																 */
		/*	   Hidden ID															 */
		/*			 Blocks															 */
		/*				   Pages per block											 */
		/*						Sectors per page									 */
		/*						   2X program										 */
		/*						   			2X read									 */
		/*											 2x status 						 */		
		/*											 		  internal Interleaving	 */		
		/*												               MLC			 */
		/*												               		   8bit ECC */
		/*****************************************************************************/
		/* MLC NAND ID TABLE */
		{0xDC, 0x14, 2048, 128, 4, TRUE32,  FALSE32, FALSE32, FALSE32, TRUE32, FALSE32},	/* 4Gb MLC(K9G4G08) Mono */
		{0xD3, 0x55, 4096, 128, 4, TRUE32,  FALSE32, FALSE32, TRUE32,  TRUE32, FALSE32},	/* 8Gb MLC(K9L8G08) DDP  */
		{0xD3, 0x14, 4096, 128, 4, TRUE32,  FALSE32, FALSE32, FALSE32, TRUE32, FALSE32},	/* 8Gb MLC(K9G8G08) Mono */
		{0xD5, 0x55, 8192, 128, 4, TRUE32,  FALSE32, FALSE32, TRUE32,  TRUE32, FALSE32},	/* 16Gb MLC(K9LAG08) DDP  */
		{0xD5, 0x14, 4096, 128, 8, TRUE32,  TRUE32,  TRUE32,  FALSE32, TRUE32, FALSE32},	/* 16Gb MLC(K9GAG08) Mono */	
		{0xD5, 0x94, 4096, 128, 8, TRUE32,  TRUE32,  TRUE32,  FALSE32, TRUE32, TRUE32},		/* 16Gb MLC(K9GAG08) Mono */ // hsjang 080922				
		{0xD7, 0x55, 8192, 128, 8, TRUE32,  TRUE32,  TRUE32,  TRUE32,  TRUE32, FALSE32},	/* 32Gb MLC(K9LBG08) DDP  */						
		{0xD7, 0xD5, 8192, 128, 8, TRUE32,  TRUE32,  TRUE32,  TRUE32,  TRUE32, TRUE32},	    /* 32Gb MLC(K9LBG08) DDP  */
};

///////////////////////////////////////////////
// PRIVATE variables definitions
///////////////////////////////////////////////
PRIVATE BOOL32 bInternalInterleaving	= FALSE32;
PRIVATE 	BOOL32 aNeedSync[WMR_MAX_DEVICE * 2];
BOOL32 bReadSafeMode = FALSE32;
UINT32 gnPpn;
BOOL32 bECCEngineError = FALSE32;

PRIVATE volatile S3C6410_NAND_REG *pNANDFConReg = NULL;
//volatile S3C6410_NAND_REG *pNANDFConReg = NULL;
PRIVATE volatile S3C6410_SYSCON_REG *pSYSConReg = NULL;
//volatile S3C6410_SYSCON_REG *pSYSConReg = NULL;
//PRIVATE volatile S3C6410_MATRIX_REG *pMatrixConReg = NULL;
PRIVATE volatile S3C6410_WATCHDOG_REG *pWTDogReg = NULL;      // VA for Watchdog base

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,
	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, UINT32* pSpareCxt, BOOL32 bCheckAllFF);
PRIVATE UINT32	Read_Sector_8BitECC(UINT32 nBank, UINT32 nPpn, UINT32 nSctOffset, UINT8* pBuf, UINT32* pSpareCxt, BOOL32 bCheckAllFF);
PRIVATE UINT32	Read_Spare(UINT32 nBank, UINT32 nPpn, UINT32* pSpareCxt);
PRIVATE UINT32	Read_Spare_Separate(UINT32 nBank, UINT32 nPpn, UINT32* pSpareCxt);
PRIVATE UINT32	Read_Spare_8BitECC(UINT32 nBank, UINT32 nPpn, UINT32* pSpareCxt);
PRIVATE VOID	Write_Sector(UINT32 nPpn, UINT32 nSctOffset, UINT8* pBuf);
PRIVATE VOID	Write_Sector_8BitECC(UINT32 nPpn, UINT32 nSctOffset, UINT8* pBuf);
PRIVATE VOID	Write_Spare(UINT32 nBank, UINT32 nPpn, pSECCCxt pSpareCxt);
PRIVATE VOID	Write_Spare_Separate(UINT32 nBank, UINT32 nPpn, pSECCCxt pSpareCxt);
PRIVATE VOID	Write_Spare_8BitECC(UINT32 nBank, UINT32 nPpn, pSECCCxt pSpareCxt);
PRIVATE UINT32	Decoding_MainECC(UINT8* pBuf);
PRIVATE UINT32	Decoding_Main8BitECC(UINT8* pBuf);
PRIVATE UINT32	Decoding_SpareECC(UINT8* pBuf);
PRIVATE UINT32	Decoding_Spare8BitECC(UINT8* pBuf, UINT32 nEffectiveByte);
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_NEED_DECODING_AGAIN					(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 ECCVAL_ALLFF0  (0xFFFFFFFF)
#define ECCVAL_ALLFF1  (0xFFFFFFFF)
#define ECCVAL_ALLFF2  (0xFFFFFFFF)
#define ECCVAL_ALLFF3  (0xFFFFFFFF)

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_500Byte_AllFF(void);
extern void _Write_Dummy_492Byte_AllFF(void);
extern void _Write_Dummy_480Byte_AllFF(void);
extern void _Write_Dummy_468Byte_AllFF(void);
extern void _Write_Dummy_448Byte_AllFF(void);
extern void _Write_Dummy_428Byte_AllFF(void);
extern void _Write_Dummy_364Byte_AllFF(void);
extern void _STOP_FOR_BREAK(void);

// WTCON - control register, bit specifications
#define WTCON_PRESCALE(x)        (((x)&0xff)<<8)    // bit 15:8, prescale value, 0 <= (x) <= 27
#define WTCON_ENABLE            (1<<5)            // bit 5, enable watchdog timer
#define WTCON_CLK_DIV16        (0<<3)
#define WTCON_CLK_DIV32        (1<<3)
#define WTCON_CLK_DIV64        (2<<3)
#define WTCON_CLK_DIV128        (3<<3)
#define WTCON_INT_ENABLE        (1<<2)
#define WTCON_RESET            (1<<0)


// WTCNT - watchdog counter register
#define WTCNT_CNT(x)            ((x)&0xffff)
// WTDAT - watchdog reload value register
#define WTDAT_CNT(x)            ((x)&0xffff)
// WTCLRINT - watchdog interrupt clear register
#define WTCLRINT_CLEAR            (1<<0)
// Watchdog Clock
// PCLK : 25MHz
// PCLK/PRESCALER : 25/25 = 1MHz
// PCLK/PRESCALER/DIVIDER : 1MHz/128 = 7.812 KHz
// MAX Counter = 0xffff = 65535
// Period = 65535/7812 =~ 8.4 sec
#define WD_PRESCALER            (25-1)
#define WD_REFRESH_PERIOD        3000    // tell the OS to refresh watchdog every 3 second.


///////////////////////////////////////////////
// Code Implementation
///////////////////////////////////////////////
#pragma optimize ("",off)

BOOL32 NF_WAIT_ECC_DEC_DONE(S3C6410_NAND_REG *pNANDFConReg)
{
    volatile int timeout;
    
	for ( timeout = 0; timeout < 1000; timeout++ )   // It need 155 cycle, but set it to enough value.
	{
	    if ( (pNANDFConReg->NFSTAT&NF_ECC_DEC_DONE) == NF_ECC_DEC_DONE )
	    {
	        return TRUE32;
	    }
	}

    bECCEngineError = TRUE32;

    return FALSE32;
}

#pragma optimize ("",on)


/*****************************************************************************/
/*                                                                           */
/* 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")));

	pNANDFConReg = (volatile S3C6410_NAND_REG *)0xB0200000;			// 0x4E000000 : 0x70200000
	//pSYSConReg   = (volatile S3C6410_SYSCON_REG *)0x92A00000;                // 0x7E00F000
	pSYSConReg   = (volatile S3C6410_SYSCON_REG *)0xB2A0F000;
	pWTDogReg    = (volatile S3C6410_WATCHDOG_REG *)0xB2A04000;
	
	// Initialize EBICON for 2nd nCE pin (nFCE1)
//#ifdef	USE_2CE_NAND
//	pMatrixConReg->EBICON |= (0x1<<8);	// Bank1_Cfg -> NAND
//#endif

/*---------------------------------------------------------
/ 2007.08.04 D.Baek
/ To fix up the malfunction of PocketMory
/---------------------------------------------------------*/
	// Configure BUS Width and Chip Select for NAND Flash
#if 1
	//pSYSConReg->MEM_SYS_CFG &= ~(1<<12);		// NAND Flash BUS Width -> 8 bit
    //pSYSConReg->MEM_SYS_CFG &= ~(0x1<<1);	// Xm0CS2 -> NFCON CS0
    pSYSConReg->MEM_SYS_CFG = (pSYSConReg->MEM_SYS_CFG & ~(0x1000)); // 8-bit data width
    pSYSConReg->MEM_SYS_CFG = (pSYSConReg->MEM_SYS_CFG & ~(0x3F)) | (0x00); // Xm0CSn[2] = NFCON CS0
/****************************************************************************/
#else
	// NAND Chip Selection Signal in the S3C6410
	pSYSConReg->MEM_SYS_CFG &= ~(0xA);
#endif
	// Initialize NAND Flash Controller for MLC NAND Flash
	pNANDFConReg->NFCONF = NF_4BIT_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
	// Set up initial flash controller configuration.
	//
	//s6410NAND->NFCONF = (NAND_TACLS  <<  12) | (NAND_TWRPH0 <<  8) | (NAND_TWRPH1 <<  4);
	//s6410NAND->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
	//s6410NAND->NFSTAT = (1<<4);
		
	/* 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;

	ECC_8BIT_SPPORT = stDEVInfo[nScanIdx].b8BitECC; // hsjang 080923 to support 8Bit ecc

	if (ECC_8BIT_SPPORT == TRUE32)
	{
        NF_SETREG_8BITECC();
    }
    
	// FS_SCAN_RATIO means scan percentage of Total FTL size.

⌨️ 快捷键说明

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