www.pudn.com > s3c2442_firmware.rar > Nand_mini.c
//==================================================================== // File Name : Nand.c // Function : S3C2442 8-bit interface Nand Test program(this program use K9k2g16.c). // Date : May xx, 2003 // Version : 0.0 // History // R0.0 (200305xx): Modified for 2442 from 2410. -> DonGo //==================================================================== /**************** K9s1206 NAND flash ********************/ // 1block=(512+16)bytes x 32pages // 4096block // Block: A[23:14], Page: [13:9] /**************** K9K2G16 NAND flash *******************/ // 1block=(2048+64)bytes x 64pages // 2048block // Block: A[23:14], page: [13:9] /*****************************************************/ #include#include #include "def.h" #include "option.h" #include "2442addr.h" #include "2442lib.h" #include "2442slib.h" #include "Nand.h" //#include "k9k2g16.h" #define ASM 1 #define C_LANG 2 #define DMA 3 #define TRANS_MODE 3 U32 srcAddress; U32 targetBlock; // Block number (0 ~ 4095) U32 targetSize; // Total byte size U32 downloadAddress; U32 downloadProgramSize=0x0; //************************************************* //************************************************* //** H/W dependent functions ** //************************************************* //************************************************* //The code is made for bi-endian mode // block0: reserved for boot strap // block1~4095: used for OS image // badblock SE: xx xx xx xx xx 00 .... // good block SE: ECC0 ECC1 ECC2 FF FF FF .... #define NF_MECC_UnLock() {rNFCONT&=~(1<<5);} #define NF_MECC_Lock() {rNFCONT|=(1<<5);} #define NF_CMD(cmd) {rNFCMD=cmd;} #define NF_ADDR(addr) {rNFADDR=addr;} #define NF_nFCE_L() {rNFCONT&=~(1<<1);} #define NF_nFCE_H() {rNFCONT|=(1<<1);} #define NF_RSTECC() {rNFCONT|=(1<<4);} #define NF_RDDATA() (rNFDATA) #define NF_RDDATA8() ((*(volatile unsigned char*)0x4E000010) ) #define NF_WRDATA(data) {rNFDATA=data;} #define NF_WAITRB() {while(!(rNFSTAT&(1<<1)));} //wait tWB and check F_RNB pin. // RnB Signal #define NF_CLEAR_RB() {rNFSTAT |= (1<<2);} // Have write '1' to clear this bit. #define NF_DETECT_RB() {while(!(rNFSTAT&(1<<2)));} #define ID_K9S1208V0M 0xec76 #define ID_K9K2G16U0M 0xecca #define NF16_BAD_OFFSET (12) // HCLK=100Mhz //#define TACLS 0 // 1-clk(0ns) //#define TWRPH0 6 // 3-clk(25ns) //#define TWRPH1 0 // 1-clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns #define TACLS 0 // 1-clk(0ns) #define TWRPH0 6 // 3-clk(25ns) #define TWRPH1 0 // 1-clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns static U8 se8Buf[16]={ 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff }; extern char *hex2char(int val); void __RdPage512(U8 *bufPt); int NF8_ReadPage(U32 block,U32 page,U8 *buffer) { int i; unsigned int blockPage; U32 ecc; U8 *bufPt=buffer; U8 se[16], ecc0, ecc1, ecc2, ecc3; page=page&0x1f; blockPage=(block<<5)+page; NF_RSTECC(); // Initialize ECC NF_MECC_UnLock(); NF_nFCE_L(); NF_CLEAR_RB(); NF_CMD(0x00); // Read command NF_ADDR(0); // Column = 0 NF_ADDR(blockPage&0xff); // NF_ADDR((blockPage>>8)&0xff); // Block & Page num. NF_ADDR((blockPage>>16)&0xff); // NF_DETECT_RB(); #if TRANS_MODE==C_LANG for(i=0;i<512;i++) { *bufPt++=NF_RDDATA8(); // Read one page } #elif TRANS_MODE==DMA // Nand to memory dma setting rSRCPND=BIT_DMA0; // Init DMA src pending. rDISRC0=NFDATA; // Nand flash data register rDISRCC0=(0<<1) | (1<<0); //arc=AHB,src_addr=fix rDIDST0=(unsigned)bufPt; rDIDSTC0=(0<<1) | (0<<0); //dst=AHB,dst_addr=inc; rDCON0=(1<<31)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(0<<23)|(1<<22)|(2<<20)|(512/4/4); //Handshake,AHB,interrupt,(4-burst),whole,S/W,no_autoreload,word,count=128; // DMA on and start. rDMASKTRIG0=(1<<1)|(1<<0); while(!(rSRCPND & BIT_DMA0)); // Wait until Dma transfer is done. rSRCPND=BIT_DMA0; #elif TRANS_MODE==ASM __RdPage512(bufPt); #endif NF_MECC_Lock(); ecc=rNFMECC0; ecc0 = (U8)(ecc &0xff); ecc1 = (U8)((ecc>>8) & 0xff); ecc2 = (U8)((ecc>>16) & 0xff); // ecc3 = (U8)((ecc>>24) & 0xff); for(i=0;i<16;i++) { se[i]=NF_RDDATA8(); // Read spare array } /* rNFMECCD0_0=NF_RDDATA8(); rNFMECCD0_1=NF_RDDATA8(); rNFMECCD0_2=NF_RDDATA8(); rNFMECCD0_3=rNFMECC0_3; */ /* rNFMECCD0=NF_RDDATA(); rNFMECCD0=((rNFMECCD0&0xffffff)|(rNFMECC0&0xff000000)); */ NF_nFCE_H(); /* if ((rNFESTAT0&0x3) == 0x0) return OK; return FAIL; */ if(ecc0==se[0] && ecc1==se[1] && ecc2==se[2] ) { //Uart_Printf("[ECC OK:%x,%x,%x,%x]\n",se[0],se[1],se[2],se[3]); return OK; } else { //Uart_Printf("[ECC ERROR(RD):read:%x,%x,%x, reg:%x,%x,%x,%x]\n", se[0],se[1],se[2],se[3],ecc0,ecc1,ecc2,ecc3); return FAIL; } } void Nand_Reset(void) { int i; NF_nFCE_L(); NF_CLEAR_RB(); NF_CMD(0xFF); //reset command NF_DETECT_RB(); NF_nFCE_H(); } void NF8_Init(void) { // for S3C2442 rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0); // TACLS [14:12] CLE&ALE duration = HCLK*TACLS. // TWRPH0 [10:8] TWRPH0 duration = HCLK*(TWRPH0+1) // TWRPH1 [6:4] TWRPH1 duration = HCLK*(TWRPH1+1) // AdvFlash(R) [3] Advanced NAND, 0:256/512, 1:1024/2048 // PageSize(R) [2] NAND memory page size // when [3]==0, 0:256, 1:512 bytes/page. // when [3]==1, 0:1024, 1:2048 bytes/page. // 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. rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0); // Lock-tight [13] 0:Disable lock, 1:Enable lock. // Soft Lock [12] 0:Disable lock, 1:Enable lock. // 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 [6] 0:Unlock, 1:Lock // MainECCLock [5] 0:Unlock, 1:Lock // InitECC(W) [4] 1:Init ECC decoder/encoder. // Reg_nCE [1] 0:nFCE=0, 1:nFCE=1. // NANDC Enable [0] operating mode. 0:Disable, 1:Enable. rNFSTAT = 0; Nand_Reset(); } int NF8_IsBadBlock(U32 block) { int i; unsigned int blockPage; U8 data; blockPage=(block<<5); // For 2'nd cycle I/O[7:5] NF_nFCE_L(); NF_CLEAR_RB(); NF_CMD(0x50); // Spare array read command NF_ADDR((512+5)&0xf); // Read the mark of bad block in spare array(M addr=5), A4-A7:Don't care NF_ADDR(blockPage&0xff); // The mark of bad block is in 0 page NF_ADDR((blockPage>>8)&0xff); // For block number A[24:17] NF_ADDR((blockPage>>16)&0xff); // For block number A[25] NF_DETECT_RB(); // Wait tR(max 12us) data=NF_RDDATA(); NF_nFCE_H(); if(data!=0xff) return FAIL; else return OK; }