📄 secnand.c
字号:
#include "system.h"
#include "Nand.h"
#include "SecNand.h"
#define __POLLING (0)
/*
* Chip ID list
*
* Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
* options
*
* Pagesize; 0, 256, 512
* 0 get this information from the extended chip ID
+ 256 256 Byte page size
* 512 512 Byte page size
*/
struct nand_flash_dev nand_flash_ids[] = {
{"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0},
{"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0},
{"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0},
{"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0},
{"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
{"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0},
{"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0},
{"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0},
{"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0},
{"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0},
{"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
{"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
{"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0},
{"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0},
{"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
{"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
{"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0},
{"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0},
{"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
{"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
{"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0},
{"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0},
{"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
{"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0},
{"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0},
{"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0},
{"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
{"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0},
/* These are the new chips with large page size. The pagesize
* and the erasesize is determined from the extended id bytes
*/
/*512 Megabit */
{"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* 1 Gigabit */
{"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* 2 Gigabit */
{"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* 4 Gigabit */
{"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* 8 Gigabit */
{"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* 16 Gigabit */
{"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
{"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
{"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
/* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
* The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
* 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
* Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
* There are more speed improvements for reads and writes possible, but not implemented now
*/
{"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH},
{NULL,}
};
static unsigned char g_uSpareData[128];
/*
* Manufacturer ID list
*/
struct nand_manufacturers nand_manuf_ids[] = {
{MAN_ID_TOSHIBA, "Toshiba"},
{MAN_ID_SAMSUNG, "Samsung"},
{MAN_ID_FUJITSU, "Fujitsu"},
{MAN_ID_NATIONAL, "National"},
{MAN_ID_RENESAS, "Renesas"},
{MAN_ID_STMICRO, "ST Micro"},
{MAN_ID_HYNIX, "Hynix"},
{0x0, "Unknown"}
};
NANDINFO sNandInfo;
extern int NFConDone;
extern int NFECCDecDone;
extern int NFECCEncDone;
#define PAGE_LEN_ECC8 512
#define VAL_LEN_ECC8 13
unsigned int PrintNandInfo(void)
{
if(!sNandInfo.uPageSize)
{
printf("\n Error : No Page Size");
}
else
{
printf("\n===========================================================");
printf("\n1th ID : 0x%x\t Manufacterer", sNandInfo.uId[0]);
printf("\n2nd ID : 0x%x\t Device ID", sNandInfo.uId[1]);
printf("\n3rh ID : 0x%x", sNandInfo.uId[2]);
printf("\n4th ID : 0x%x", sNandInfo.uId[3]);
printf("\n5th ID : 0x%x", sNandInfo.uId[4]);
printf("\nNand Size : %ld MB, \t%d B", sNandInfo.uNandSize>>20, sNandInfo.uNandSize);
printf("\nPage Size : %d Bytes", sNandInfo.uPageSize);
printf("\nBlock Size : %d KBytpes\n", sNandInfo.uBlockSize >> 10);
printf("\n512Bytes Per Page : %d", sNandInfo.u512BytesPerPage);
printf("\nNand Col Cycle : %d", sNandInfo.uColCycle);
printf("\nNand Row Cycle : %d", sNandInfo.uRowCycle);
printf("\nNand Row Addr By Block Size : %d", sNandInfo.uBlockShift);
printf("\nPages per Block : %d pages\n", sNandInfo.uPagesPerBlock);
printf("\nNand Total Address : A%d", sNandInfo.uAddrCycleNum);
printf("\nIs MLC ? : %d", sNandInfo.uIsMLC);
printf("\nInter Chip Number : %d", sNandInfo.uIntChipNum);
printf("\nCell Type : %d Level Cell", sNandInfo.uCellType);
printf("\nNumber of Simultaneously Programmed Pages : %d", sNandInfo.uNSimProgPages);
printf("\nInterleave Program Between multiple chips : %d", sNandInfo.uInterleaveProg);
printf("\nCache Program : %d", sNandInfo.uCacheProg);
printf("\nRedundant Area Size : %d(byte/512bytes)", sNandInfo.uRedundantAreaSize);
printf("\nOrganization : x%d", sNandInfo.uOrganization);
printf("\nSerial Access Minimum : %d", sNandInfo.uSerialAccessMin);
printf("\nPlane Number : %d", sNandInfo.uPlaneNum);
printf("\nPlane Size : %dMB", sNandInfo.uPlaneSize>>20);
printf("\n===========================================================");
}
return 0;
}
void ResetNand(void)
{
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(CMD_RESET); //reset command
NF_DETECT_RB();
NF_nFCE_H();
}
/////// for S3C2450 ///////////////////////////////////////////////////////////
//--> [NFCONF]
// TACLS [14:12] CLE&ALE duration = HCLK*TACLS.
// TWRPH0 [10:8] TWRPH0 duration = HCLK*(TWRPH0+1)
// TWRPH1 [6:4] TWRPH1 duration = HCLK*(TWRPH1+1)
// PageSize(R) [3] NAND memory page size
// when [3]==0, 0:512, 1:2048 bytes/page.
// when [3]==1, 0:2048, 1:4096 bytes/page by PageSize_Ext
// PageSize_Ext(R) [2] when [2]==0, Small Size Nand Flash
// when [2]==1, Large Size Nand Flash
// AddrCycle(R) [1] NAND flash addr size
// when [3]==0, 0:3-addr, 1:4-addr.
// when [3]==1, 0:4-addr, 1:5-addr.
// BusWidth(R/W) [0] NAND bus width. 0:8-bit, 1:16-bit.
//--> [NFCONT]
// ECC Direction [18] 0:Decoding(4/8 ECC)
// 1:Encoding(4/8 ECC)
// Lock-tight [17] 0:Disable lock, 1:Enable lock.
// Soft Lock [16] 0:Disable lock, 1:Enable lock.
// EnbECCDecINT [12] 0:Disable Interrupt, 1:Enable Interrupt (Enable/Disable 4/8ECC decoding Done Interrupt)
// 8bit Stop [11] 8-bit ECC en/decoding operation initialization
// EnablillegalAcINT[10] Illegal access interupt control. 0:Disable, 1:Enable
// EnbRnBINT [9] RnB interrupt. 0:Disable, 1:Enable
// RnB_TrandMode [8] RnB transition detection config. 0:Low to High, 1:High to Low
// SpareECCLock [7] 0:Unlock, 1:Lock
// MainECCLock [6] 0:Unlock, 1:Lock
// InitMECC(W) [5] 1:Init main area ECC decoder/encoder.
// InitSECC(W) [4] 1:Init spare area ECC decoder/encoder.
// Reg_nCE1 [2] 0:nFCE=0, 1:nFCE=1.
// Reg_nCE0 [1] 0:nFCE=0, 1:nFCE=1.
// NANDC Enable [0] operating mode. 0:Disable, 1:Enable.
void * nfc_func[][2]=
{
(void *)ReadID, "Read ID ",
(void *)ResetNand, "Nand reset ",
(void *)TestEraseBlock, "Erase Block ",
(void *)TestReadPage, "Read Page ",
(void *)TestWritePage, "Write Page ",
(void *)Test_Lock, "Lock Test ",
(void *)ClearSoftLock, "Clear Soft Lock ",
(void *)WriteDramImage2Nand,"Write Dram Image",
(void *)ReadNandImage2Dram, "Read From Nand ",
0,0
};
static void PrintSubMessage(void)
{
int i;
i=0;
printf("\n\n");
while(1)
{ //display menu
printf("%2d:%s",i,nfc_func[i][1]);
i++;
if((int)(nfc_func[i][0])==0)
{
printf("\n");
break;
}
if((i%4)==0) printf("\n");
}
}
void TestNFC(void)
{
int i;
ReadID();
while(1)
{
PrintSubMessage();
printf("\nSelect(-1 to exit): ");
i = GetIntNum();
if(i==-1) break;
if(i>=0 && (i<(sizeof(nfc_func)/8)) )
( (void (*)(void)) (nfc_func[i][0]) )(); // execute selected function.
}
}
//Normal Initalization of NFC
void InitNFC(void)
{
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
rNFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
}
void ReadID(void)
{
unsigned char uId[16], i, uScan;
unsigned int uTemp, uSize;
memset(&sNandInfo,0,sizeof(NANDINFO));
InitNFC();
printf("\nK9F5608 : 2 IDs");
printf("\nK9F1208 : 4 IDs");
printf("\nK9HBG08U1M / K9MZG08U3M / K9LAG08U0M / K9MCG08U5M : 5 IDs");
printf("\nK9GAG08U0M / K9HCG08U5M / K9GAG08B0M / K9LBG08U1M : 5 IDs");
printf("\n\nHow Many IDs? (2/3/4/5/6/7) : ");
sNandInfo.uNId = 5;
NF_nFCE_L();
NF_CMD(CMD_READID);
NF_ADDR(0x00);
for (i=0; i<10; i++);//delay
for(i=0; i<sNandInfo.uNId; i++)
sNandInfo.uId[i] = NF_RDDATA8();
NF_nFCE_H();
if((sNandInfo.uId[0]==0xEC || sNandInfo.uId[0]==0x98) && ((sNandInfo.uId[1]==0x76)||(sNandInfo.uId[1]==0x75))) sNandInfo.uNId = 4;
if(sNandInfo.uNId < 5)
{
sNandInfo.uPageSize = 512;
sNandInfo.uNandSize = 64*1024*1024;
sNandInfo.uColCycle = 1;
if((sNandInfo.uId[1]==0x75))
{
sNandInfo.uRowCycle = 2;
}
else
{
sNandInfo.uRowCycle = 3;
}
sNandInfo.uBlockSize = 16*1024;
sNandInfo.u512BytesPerPage = 1;
sNandInfo.uRedundantAreaSize = 16;
//Scan Cell Type
uTemp = (sNandInfo.uId[2]>>2)& 0x03;
sNandInfo.uCellType = 1;
for(i=0;i<=uTemp;i++) sNandInfo.uCellType *= 2;
sNandInfo.uIsMLC = uTemp;
}
else
{
//------> 3rd ID
uTemp = sNandInfo.uId[2]& 0x03;
//Scan Internal Chip Number
sNandInfo.uIntChipNum = 1;
for(i=0;i<uTemp;i++) sNandInfo.uIntChipNum *= 2;
//Scan Cell Type
uTemp = (sNandInfo.uId[2]>>2)& 0x03;
sNandInfo.uCellType = 1;
for(i=0;i<=uTemp;i++) sNandInfo.uCellType *= 2;
sNandInfo.uIsMLC = uTemp;
uTemp = (sNandInfo.uId[2]>>4)& 0x03;
sNandInfo.uNSimProgPages = 1;
for(i=0;i<uTemp;i++) sNandInfo.uNSimProgPages *= 2;
sNandInfo.uInterleaveProg = (sNandInfo.uId[2]>>6)& 0x01;
sNandInfo.uCacheProg = (sNandInfo.uId[2]>>7)& 0x01;
//------> 4th ID
uTemp = sNandInfo.uId[3]& 0x03;
sNandInfo.uPageSize = 1024;
for(i=0;i<uTemp;i++) sNandInfo.uPageSize *=2;
sNandInfo.u512BytesPerPage = sNandInfo.uPageSize >> 9;
uTemp = (sNandInfo.uId[3]>>2)& 0x01;
if(uTemp) sNandInfo.uRedundantAreaSize = 16;
else sNandInfo.uRedundantAreaSize = 8;
uTemp = (sNandInfo.uId[3]>>4)& 0x03;
sNandInfo.uBlockSize = 64*1024;
for(i=0;i<uTemp;i++) sNandInfo.uBlockSize *=2;
uTemp = (sNandInfo.uId[3]>>6)& 0x01;//TBD
if(uTemp) sNandInfo.uOrganization = 16;
else sNandInfo.uOrganization = 8;
//------> 5th ID
uTemp = (sNandInfo.uId[4]>>2)& 0x03;
sNandInfo.uPlaneNum = 1;
for(i=0;i<uTemp;i++) sNandInfo.uPlaneNum *= 2;
uTemp = (sNandInfo.uId[4]>>4)& 0x07;
sNandInfo.uPlaneSize = (8388608); //64*1024*1024/8
for(i=0;i<uTemp;i++) sNandInfo.uPlaneSize *=2;
sNandInfo.uNandSize = sNandInfo.uPlaneNum*sNandInfo.uPlaneSize;
uTemp = sNandInfo.uPageSize;
for(i=0; uTemp>1; i++) uTemp>>=1;
uTemp = i;
sNandInfo.uAddrCycleNum+=uTemp;
for(i=1; uTemp>8; i++) uTemp-=8;
sNandInfo.uColCycle = i;
uTemp = sNandInfo.uPageSize;
uSize = sNandInfo.uNandSize;
for(i=0; uTemp>1; i++)
{
uTemp>>=1;
uSize>>=1;
}
for(i=0; uSize>1; i++) uSize>>=1;
uSize = i;
sNandInfo.uAddrCycleNum+=uSize;
for(i=1; uSize>8; i++) uSize-=8;
sNandInfo.uRowCycle = i;
}
sNandInfo.uAddrCycle = sNandInfo.uColCycle + sNandInfo.uRowCycle;
uTemp = sNandInfo.uPageSize;
uSize = sNandInfo.uBlockSize;
for(i=0; uTemp>1; i++)
{
uTemp>>=1;
uSize>>=1;
}
if(sNandInfo.u512BytesPerPage > 1) //large block
{
rNFCONF |= (1<<2);
if(sNandInfo.uAddrCycle ==4) //addr cycle : 4
{
rNFCONF &= ~(1<<1);
if(sNandInfo.u512BytesPerPage == 4)
{
rNFCONF &= ~(1<<3);
}
else
{
rNFCONF |= (1<<3);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -