?? s3c6410_fil.c
字號(hào):
///////////////////////////////////////////////////////////////
//
// 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.
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -