📄 fmd.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <fmd.h>
#include <s3c2443_nand.h>
#include <args.h>
#include <ethdbg.h>
#include "Cfnand.h"
#define IO_INDICATE 0
#if IO_INDICATE==1
#include <s3c2443_ioport.h> //DonGo
#endif //IO_INDICATE
#define NAND_BASE 0xB1400000 // PA:0x4e00_0000
#if IO_INDICATE==1
#define IOPORT_BASE 0xB2100000 // PA:0x56000000 //DonGo
#endif //IO_INDICATE
BOOL NEED_EXT_ADDR = TRUE;
static volatile S3C2443_NAND_REG *s2443NAND = (S3C2443_NAND_REG *)NAND_BASE;
#if IO_INDICATE==1
static volatile S3C2443_IOPORT_REG *s2443IOPORT = (S3C2443_IOPORT_REG *)IOPORT_BASE; //DonGo
#endif //IO_INDICATE
#if MAGNETO
BSP_ARGS *pBSPArgs;
#endif
extern "C" void RdPage512(unsigned char *bufPt);
extern "C" void RdPage512Unalign(unsigned char *bufPt);
extern "C" void WrPage512(unsigned char *bufPt);
extern "C" void WrPage512Unalign(unsigned char *bufPt);
extern "C" void WrPageInfo(PBYTE pBuff);
extern "C" void RdPageInfo(PBYTE pBuff);
/*
@func DWORD | ReadFlashID | Reads the flash manufacturer and device codes.
@rdesc Manufacturer and device codes.
@comm
@xref
*/
static DWORD ReadFlashID(void)
{
BYTE Mfg, Dev;
NF_nFCE_L(); // Deselect the flash chip.
NF_CMD(CMD_READID); // Send flash ID read command.
NF_ADDR(0); //
Mfg = NF_RDDATA_BYTE(); //
Dev = NF_RDDATA_BYTE(); //
NF_nFCE_H(); // Deselect the flash chip.
return ((DWORD)(Mfg<<8)+Dev);
}
/*
@func PVOID | FMD_Init | Initializes the Smart Media NAND flash controller.
@rdesc Pointer to S3C2443 NAND controller registers.
@comm
@xref
*/
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
// Caller should have specified NAND controller address.
//
BOOL bLastMode = SetKMode(TRUE);
volatile DWORD rdid;
RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_INIT \r\n")));
#if MAGNETO
pBSPArgs = ((BSP_ARGS *) IMAGE_SHARE_ARGS_UA_START);
#endif
if (pRegIn && pRegIn->MemBase.Num && pRegIn->MemBase.Reg[0])
s2443NAND = (S3C2443_NAND_REG *)(pRegIn->MemBase.Reg[0]);
else
s2443NAND = (S3C2443_NAND_REG *)NAND_BASE;
#if IO_INDICATE==1
s2443IOPORT = (S3C2443_IOPORT_REG *)IOPORT_BASE; //DonGo
s2443IOPORT->GPGCON = (s2443IOPORT->GPGCON & ~(0x3<<2)) | (0x1<<2); // GPG1 //DonGo
//s2443IOPORT->DSC1 = (s2443IOPORT->DSC1 & ~(0x3<<10)) | (0x3<<10); // Drive strength
#endif
// Set up initial flash controller configuration.
//
s2443NAND->NFCONF = (TACLS << 12) | /* CLE & ALE = HCLK * (TACLS + 1) */
(TWRPH0 << 8) | /* TWRPH0 = HCLK * (TWRPH0 + 1) */
(TWRPH1 << 4);
s2443NAND->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
s2443NAND->NFSTAT = (1<<4);
RETAILMSG(1, (TEXT("NAND Read ID...")));
/*
NF_CLEAR_RB();
NF_nFCE_L(); // Select the flash chip.
NF_CLEAR_RB();
NF_CMD(CMD_RESET); // Send reset command.
//for(volatile int i=0; i<30; i++);
NF_DETECT_RB(); // Wait for flash to complete command.
NF_nFCE_H(); // Deselect the flash chip.
*/
// Get manufacturer and device codes.
rdid = ReadFlashID();
if (rdid != 0xEC76 && rdid!= 0x9876 && rdid!=0x9879 && rdid!=0xecda && rdid!=0x987e )
// 0xec76: SOP, 0x9876:64MB XD, 0x9879:64MB XD, 0x987e:64MB XD, 0xecda:256MB SOP
{
RETAILMSG(1, (TEXT("Error!!!(%x)\n"), rdid));
//NF_nFCE_H(); // Deselect the flash chip.
SetKMode (bLastMode);
return(NULL);
}
else
{
RETAILMSG(1, (TEXT("OK(%x).\n"), rdid));
}
SetKMode (bLastMode);
return((PVOID)s2443NAND);
}
/*
@func BOOL | FMD_ReadSector | Reads the specified sector(s) from NAND flash.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
BOOL bRet;
// RETAILMSG(1, (TEXT("FMD::FMD_ReadSector 0x%x \r\n"), startSectorAddr));
if ( startSectorAddr < (unsigned)wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
bRet = FMD_LB_ReadSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
else
bRet = FMD_SB_ReadSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
}
else
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
bRet = FMD_LB_ReadSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
else
bRet = FMD_SB_ReadSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
}
// RETAILMSG(1, (TEXT("FMD::FMD_ReadSector -- \r\n")));
return bRet;
}
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff,
DWORD dwNumSectors)
{
BOOL bRet = TRUE;
// RETAILMSG(1, (TEXT("FMD::FMD_WriteSector 0x%x \r\n"), startSectorAddr));
if ( startSectorAddr < (unsigned)wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
bRet = FMD_LB_WriteSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
else
bRet = FMD_SB_WriteSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
}
else // if ( PRIMARY_NAND == SMALL_BLOCK_NAND )
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
bRet = FMD_LB_WriteSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
else
bRet = FMD_SB_WriteSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
}
return bRet;
}
/*
@func BOOL | FMD_EraseBlock | Erases the specified flash block.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
// RETAILMSG(1, (TEXT("FMD::FMD_EraseBlock 0x%x \r\n")));
BOOL bRet = TRUE;
int i;
if ( blockID < wPRIMARY_NAND_BLOCKS )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = FMD_LB_EraseBlock(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = FMD_SB_EraseBlock(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
}
else
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = FMD_LB_EraseBlock((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = FMD_SB_EraseBlock(blockID*(SB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
}
return bRet;
}
VOID FMD_PowerUp(VOID)
{
// Set up initial flash controller configuration.
//
s2443NAND->NFCONF = (TACLS << 12) | /* CLE & ALE = HCLK * (TACLS + 1) */
(TWRPH0 << 8) | /* TWRPH0 = HCLK * (TWRPH0 + 1) */
(TWRPH1 << 4);
s2443NAND->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
s2443NAND->NFSTAT = (1<<4);
}
VOID FMD_PowerDown(VOID)
{
}
BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
return(TRUE);
}
BOOL FMD_Deinit(PVOID hFMD)
{
return(TRUE);
}
/*
@func BOOL | FMD_GetInfo | Provides information on the NAND flash.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
UINT32 nCnt;
UINT32 nNandID;
UINT8 nMID, nDID;
if (!pFlashInfo)
return(FALSE);
BOOL bLastMode = SetKMode(TRUE); // for READFlashID();
pFlashInfo->flashType = NAND;
nNandID = ReadFlashID();
nMID = nNandID >> 8;
nDID = nNandID & 0xff;
for (nCnt = 0; astNandSpec[nCnt].nMID != 0; nCnt++)
{
if (nDID == astNandSpec[nCnt].nDID)
{
break;
}
}
dwPrimaryNandDevice = nCnt;
wPRIMARY_REAL_NAND_BLOCKS = astNandSpec[dwPrimaryNandDevice].nNumOfBlks;
wSECONDARY_NAND_BLOCKS = 0;
wSECONDARY_REAL_NAND_BLOCKS = 0;
// RETAILMSG(1, (TEXT("dwPrimaryNandDevice : %d(0x%x) \r\n"), dwPrimaryNandDevice, dwPrimaryNandDevice));
// RETAILMSG(1, (TEXT("astNandSpec[dwPrimaryNandDevice].nSctsPerPg: %d(0x%x) \r\n"), astNandSpec[dwPrimaryNandDevice].nSctsPerPg, astNandSpec[dwPrimaryNandDevice].nSctsPerPg));
// RETAILMSG(1, (TEXT("wPRIMARY_REAL_NAND_BLOCKS : %d(0x%x) \r\n"), wPRIMARY_REAL_NAND_BLOCKS, wPRIMARY_REAL_NAND_BLOCKS));
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 ) // Primary NAND is Large Block...
{
wPRIMARY_NAND_BLOCKS = wPRIMARY_REAL_NAND_BLOCKS;
}
else
{
wPRIMARY_NAND_BLOCKS = wPRIMARY_REAL_NAND_BLOCKS / 8;
}
wNUM_BLOCKS = wPRIMARY_NAND_BLOCKS + wSECONDARY_NAND_BLOCKS;
// OK, instead of reading it from the chip, we use the hardcoded
// numbers here.
pFlashInfo->dwNumBlocks = wNUM_BLOCKS;
pFlashInfo->wSectorsPerBlock = NAND_PAGE_CNT;
pFlashInfo->wDataBytesPerSector = NAND_PAGE_SIZE;
pFlashInfo->dwBytesPerBlock = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
RETAILMSG(1, (TEXT("NUMBLOCKS : %d(0x%x), SECTORSPERBLOCK = %d(0x%x), BYTESPERSECTOR = %d(0x%x) \r\n"), pFlashInfo->dwNumBlocks, pFlashInfo->dwNumBlocks, pFlashInfo->wSectorsPerBlock, pFlashInfo->wSectorsPerBlock, pFlashInfo->wDataBytesPerSector, pFlashInfo->wDataBytesPerSector));
SetKMode(bLastMode);
return TRUE;
}
#define VALIDADDR 0x05 // S3C2443NAND
static BOOL IsBlockBad(BLOCK_ID blockID)
{
BOOL bRet = FALSE;
int i;
if ( blockID < wPRIMARY_NAND_BLOCKS )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = LB_IsBlockBad(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == TRUE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = SB_IsBlockBad(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == TRUE ) break;
}
}
}
else
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = LB_IsBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == TRUE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = SB_IsBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == TRUE ) break;
}
}
}
return bRet;
}
/*
@func DWORD | FMD_GetBlockStatus | Returns the status of the specified block.
@rdesc Block status (see fmd.h).
@comm
@xref
*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
DWORD dwResult = 0;
int i;
if ( blockID < wPRIMARY_NAND_BLOCKS )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
dwResult |= FMD_LB_GetBlockStatus(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
dwResult |= FMD_SB_GetBlockStatus(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
}
}
}
else
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
dwResult |= FMD_LB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
dwResult |= FMD_SB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
}
}
}
return dwResult;
}
/*
@func BOOL | MarkBlockBad | Marks the specified block as bad.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
static BOOL MarkBlockBad(BLOCK_ID blockID)
{
BOOL bRet = TRUE;
int i;
if ( blockID < wPRIMARY_NAND_BLOCKS )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = LB_MarkBlockBad(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = SB_MarkBlockBad(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
}
else // if ( PRIMARY_NAND == SMALL_BLOCK_NAND )
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = LB_MarkBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = SB_MarkBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
}
return bRet;
}
/*
@func BOOL | FMD_SetBlockStatus | Marks the block with the specified block status.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
BOOL bRet = TRUE;
int i;
if ( blockID < wPRIMARY_NAND_BLOCKS )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = FMD_LB_SetBlockStatus(blockID*(LB_BLOCK_LOOP) + i, dwStatus, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = FMD_SB_SetBlockStatus(blockID*(SB_BLOCK_LOOP) + i, dwStatus, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
}
else // if ( PRIMARY_NAND == SMALL_BLOCK_NAND )
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = FMD_LB_SetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, dwStatus, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = FMD_SB_SetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, dwStatus, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
}
return bRet;
}
BOOL FMD_LB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors,int mode)
{
ULONG SectorAddr = (ULONG)startSectorAddr;
// ULONG MECC;
DWORD i;
BYTE eccBuf[8];
volatile DWORD rddata;
int NewSpareAddr = 2048 + 16*(startSectorAddr%4);
int NewDataAddr = 512*(startSectorAddr%4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -