?? nand.c
字號:
//////////
// Function Name : NAND_CheckECCError
// Function Description : This function check the ECC Error
// Input : Controller - Nand Controller Port Number
// Output : ECC Error Type
NAND_eERROR NAND_CheckECCError(u32 Controller)
{
u32 uEccError0;
//u32 uEccError1;
NAND_eERROR eError;
eError = eNAND_NoError;
if((NAND_Inform[Controller].uNandType == NAND_Normal8bit) || (NAND_Inform[Controller].uNandType == NAND_Advanced8bit) )
{
uEccError0 = Inp32(&NAND(Controller)->rNFECCERR0);
switch (uEccError0 & 0x03)
{
case 0x00 : eError = eNAND_NoError;
break;
case 0x01 : eError = eNAND_1bitEccError;
break;
case 0x02 : eError = eNAND_MultiError;
break;
case 0x03 : eError = eNAND_EccAreaError;
break;
}
if(NAND_Inform[Controller].uPerformanceCheck == 0)
{
switch ((uEccError0 & 0x0C)>>2)
{
case 0x00 : eError |= eNAND_NoError;
break;
case 0x01 : eError |= eNAND_Spare1bitEccError;
break;
case 0x02 : eError |= eNAND_SpareMultiError;
break;
case 0x03 : eError |= eNAND_SpareEccAreaError;
break;
}
}
}
else if(NAND_Inform[Controller].uNandType == NAND_MLC8bit)
{
uEccError0 = Inp32(&NAND(Controller)->rNFECCERR0);
//uEccError1 = Inp32(&NAND(Controller)->rNFECCERR1);
switch ((uEccError0>>26) & 0x07)
{
case 0x00 : eError = eNAND_NoError;
break;
case 0x01 : eError = eNAND_1bitEccError;
break;
case 0x02 : eError = eNAND_2bitEccError;
break;
case 0x03 : eError = eNAND_3bitEccError;
break;
case 0x04 : eError = eNAND_4bitEccError;
break;
case 0x05 : eError = eNAND_UncorrectableError;
break;
}
}
return eError;
}
//////////
// Function Name : NAND_SeekECCErrorPosition
// Function Description : This function seek the ECC error position
// Input : Controller - Nand Controller Port Number
// uEccErr0 - the variable address to return the rNFECCERR0 register value
// uEccErr1 - the variable address to return the rNFECCERR1 register value
// uEccErr2 - the variable address to return the rNFMLCBITPT register value
// Output : ECC error register0/1 & Bit Pattern register value
void NAND_SeekECCErrorPosition(u32 Controller, u32 *uEccErr0, u32 *uEccErr1, u32 *uEccErr2)
{
if(NAND_Inform[Controller].uNandType == NAND_MLC8bit)
{
*uEccErr0 = Inp32(&(NAND(Controller)->rNFECCERR0));
*uEccErr1 = Inp32(&(NAND(Controller)->rNFECCERR1));
*uEccErr2 = Inp32(&(NAND(Controller)->rNFMLCBITPT));
}
else
{
*uEccErr0 = Inp32(&(NAND(Controller)->rNFECCERR0));
}
}
//////////
// Function Name : NAND_ReadPageSLC
// Function Description : This function read the 1 page data of external SLC Type NAND device
// Input : Controller - Nand Controller Port Number
// uBlock - Read Block
// uPage - Read Page
// pBuffer - Read data buffer
// Output : ECC Error Type
NAND_eERROR NAND_ReadPageSLC(u32 Controller, u32 uBlock, u32 uPage, u8 *pBuffer, u8 *pSpareBuffer)
{
u32 i, uBlockPage, uPageSize;
u32 uMecc, uSecc;
NAND_eERROR eError;
u32 *pBufferW;
pBufferW = (u32 *)pBuffer;
if(NAND_Inform[Controller].uNandType == NAND_Normal8bit)
{
uBlockPage=(uBlock<<5) + uPage;
uPageSize = NAND_Inform[Controller].uPageSize;
}
else //if(NAND_Inform[Controller].uNandType == NAND_Advanced8bit)
{
uBlockPage=(uBlock<<6) + uPage;
uPageSize = NAND_Inform[Controller].uPageSize;
}
NF_RSTECC(Controller); // Initialize ECC
NF_MECC_UnLock(Controller);
NF_nFCE_L(Controller);
NF_CLEAR_RnB(Controller);
//if(NAND_Inform[Controller].uNandType == NAND_Normal8bit)
if(NAND_Inform[Controller].uAddrCycle == 4)
{
NF_CMD(Controller, 0x00); // Read command
NF_ADDR(Controller, 0);
}
else if(NAND_Inform[Controller].uAddrCycle == 5)
{
NF_CMD(Controller, 0x00); // 1st Read command
NF_ADDR(Controller, 0);
NF_ADDR(Controller, 0);
}
NF_ADDR(Controller, uBlockPage&0xff); //
NF_ADDR(Controller, (uBlockPage>>8)&0xff); // Block & Page num.
NF_ADDR(Controller, (uBlockPage>>16)&0xff); //
if(NAND_Inform[Controller].uNandType == NAND_Advanced8bit)
NF_CMD(Controller, 0x30); // 2'nd command
NF_DETECT_RnB(Controller);
#if NAND_TRANSFER_MODE == POLLING_TRANSFER
#if 0
for(i=0 ; i<uPageSize ; i++)
{
*pBuffer++ = NF_RDDATA8(Controller); // Read one page
}
#else
for(i=0 ; i<uPageSize/4 ; i++)
{
*pBufferW++ = NF_RDDATA(Controller); // Read one page
}
#endif
#elif NAND_TRANSFER_MODE == DMA_TRANSFER
Nand_DmaDone = 0;
DMACH_Setup(DMA_A, 0x0, (u32)(&(NAND(Controller)->rNFDATA)), 1, (u32)pBufferW, 0, WORD, uPageSize/4, DEMAND, DMA1_NAND_TX, MEM, BURST128, &g_oNandDmac1);
DMACH_Start(&g_oNandDmac1);
while(!Nand_DmaDone);
#endif
NF_MECC_Lock(Controller);
if(NAND_Inform[Controller].uNandType == NAND_Normal8bit)
{
NF_SECC_UnLock(Controller);
// Main Area ECC Check(1st ~ 4th byte : Main Area ECC Information)
uMecc = NF_RDDATA(Controller);
if(NAND_Inform[Controller].uSpareECCtest == 0)
{
Outp32(&NAND(Controller)->rNFMECCD0, ((uMecc&0xff00)<<8)|(uMecc&0xff) );
Outp32(&NAND(Controller)->rNFMECCD1, ((uMecc&0xff000000)>>8)|((uMecc&0xff0000)>>16) );
}
else if(NAND_Inform[Controller].uSpareECCtest == 1)
{
// The correct MECC value is written for SpareECC Test
u32 uTempMecc;
uTempMecc = ((u32)aNand_Spare_Data_Temp[3]<<24)|
((u32)aNand_Spare_Data_Temp[2]<<16)|
((u32)aNand_Spare_Data_Temp[1]<<8)|
((u32)aNand_Spare_Data_Temp[0]);
Outp32(&NAND(Controller)->rNFMECCD0, ((uTempMecc&0xff00)<<8)|(uTempMecc&0xff) );
Outp32(&NAND(Controller)->rNFMECCD1, ((uTempMecc&0xff000000)>>8)|((uTempMecc&0xff0000)>>16) );
}
NF_SECC_Lock(Controller);
aNand_Spare_Data[0] = (u8)(uMecc&0xFF);
aNand_Spare_Data[1] = (u8)((uMecc&0xFF00)>>8);
aNand_Spare_Data[2] = (u8)((uMecc&0xFF0000)>>16);
aNand_Spare_Data[3] = (u8)((uMecc&0xFF000000)>>24);
aNand_Spare_Data[4] = NF_RDDATA8(Controller); // read 5th byte(dummy)
}
else if(NAND_Inform[Controller].uNandType == NAND_Advanced8bit)
{
aNand_Spare_Data[0] = NF_RDDATA8(Controller); // Invalid Block Check data
NF_SECC_UnLock(Controller);
// Main Area ECC Check
uMecc = NF_RDDATA(Controller);
if(NAND_Inform[Controller].uSpareECCtest == 0)
{
Outp32(&NAND(Controller)->rNFMECCD0, ((uMecc&0xff00)<<8)|(uMecc&0xff) );
Outp32(&NAND(Controller)->rNFMECCD1, ((uMecc&0xff000000)>>8)|((uMecc&0xff0000)>>16) );
}
NF_SECC_Lock(Controller);
aNand_Spare_Data[1] = (u8)(uMecc&0xFF);
aNand_Spare_Data[2] = (u8)((uMecc&0xFF00)>>8);
aNand_Spare_Data[3] = (u8)((uMecc&0xFF0000)>>16);
aNand_Spare_Data[4] = (u8)((uMecc&0xFF000000)>>24);
}
for(i=5; i<NAND_Inform[Controller].uSpareSize ; i++)
{
aNand_Spare_Data[i] = NF_RDDATA8(Controller);
}
for(i=0; i<NAND_Inform[Controller].uSpareSize ; i++)
*pSpareBuffer++ = aNand_Spare_Data[i];
// Spare Area ECC Check
uSecc = (aNand_Spare_Data[9]<<8) | (aNand_Spare_Data[8]);
Outp32(&NAND(Controller)->rNFSECCD, ((uSecc&0xff00)<<8)|(uSecc&0xff) );
NF_nFCE_H(Controller);
eError = NAND_CheckECCError(Controller);
return eError;
}
//////////
// Function Name : NAND_ReadPageMLC
// Function Description : This function read the 1 page data of external MLC Type NAND device
// Input : Controller - Nand Controller Port Number
// uBlock - Read Block
// uPage - Read Page
// pBuffer - Read data buffer
// Output : Nand Error Type
NAND_eERROR NAND_ReadPageMLC(u32 Controller, u32 uBlock, u32 uPage, u8 *pBuffer, u8 *pSpareBuffer)
{
u32 i, uBlockPage, uPageSize, uTemp;
NAND_eERROR eError;
u32 *pBufferW;
pBufferW = (u32 *)pBuffer;
g_Nand_4bitEccDecDone = 0;
uTemp = NAND_ReadNFCONRegister(Controller);
//uTemp |= (1<<12); // 4bit ECC decoding Interrupt enable
uTemp |= (1<<12)|(1<<13); // 4bit ECC decoding/encoding Interrupt enable...because error
uTemp &= ~(1<<18); // Decoding 4bit ECC selection
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
Outp32(&(NAND(Controller)->rNFSTAT), (1<<6)); // 4bit ECC Decoding finish bit clear
INTC_Enable(NUM_NFC);
uBlockPage=(uBlock<<7) + uPage;
uPageSize = NAND_Inform[Controller].uPageSize;
//////////////////////////
// Read 0 ~ 511
//////////////////////////
NF_RSTECC(Controller); // Initialize ECC
NF_MECC_UnLock(Controller);
NF_nFCE_L(Controller);
#if (NAND_REG_BUG == TRUE)
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp |= (1<<12)|(1<<13); // 4bit ECC decoding/encoding Interrupt enable...because error
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
#endif
NF_CLEAR_RnB(Controller);
NF_CMD(Controller, 0x00); // 1st Read command
NF_ADDR(Controller, 0);
NF_ADDR(Controller, 0);
NF_ADDR(Controller, uBlockPage&0xff); //
NF_ADDR(Controller, (uBlockPage>>8)&0xff); // Block & Page num.
NF_ADDR(Controller, (uBlockPage>>16)&0xff); //
NF_CMD(Controller, 0x30); // 2'nd command
NF_DETECT_RnB(Controller);
#if NAND_TRANSFER_MODE == POLLING_TRANSFER
#if 0
for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) // MLC ECC Size : 512bytes
{
*pBuffer++ = NF_RDDATA8(Controller); // Read one page
}
#else
for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++)
{
*pBufferW++ = NF_RDDATA(Controller); // Read one page
}
#endif
#elif NAND_TRANSFER_MODE == DMA_TRANSFER
Nand_DmaDone = 0;
DMACH_Setup(DMA_A, 0x0, (u32)(&(NAND(Controller)->rNFDATA)), 1, (u32)pBufferW, 0, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, DMA1_NAND_TX, MEM, BURST128, &g_oNandDmac1);
DMACH_Start(&g_oNandDmac1);
while(!Nand_DmaDone);
pBufferW += NAND_MLC_TRANS_SIZE/4;
#endif
//NF_MECC_Lock(Controller);
NF_CMD(Controller, 0x05);
NF_ADDR(Controller, (uPageSize+1)&0xFF);
NF_ADDR(Controller, ((uPageSize+1)>>8)&0xFF);
NF_CMD(Controller, 0xE0);
pSpareBuffer++;
for(i=1 ; i<8 ; i++)
{
aNand_Spare_Data[i] = NF_RDDATA8(Controller);
if(NAND_Inform[Controller].uPerformanceCheck == 0)
*pSpareBuffer++ = aNand_Spare_Data[i];
}
while(g_Nand_4bitEccDecDone == 0);
eError = NAND_CheckECCError(Controller);
if(eError != eNAND_NoError)
{
NF_MECC_Lock(Controller);
NF_nFCE_H(Controller);
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp &= ~((1<<12)|(1<<13)); // 4bit ECC decoding Interrupt disable
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
NAND_Inform[Controller].uMLCECCPageReadSector = 0; //0 ~ 511 Bytes
return eError;
}
//////////////////////////
// Read 512 ~ 1023
//////////////////////////
g_Nand_4bitEccDecDone = 0;
NF_RSTECC(Controller); // Initialize ECC
#if (NAND_REG_BUG == TRUE)
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp |= (1<<12)|(1<<13); // 4bit ECC decoding/encoding Interrupt enable...because error
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
#endif
NF_CMD(Controller, 0x05);
NF_ADDR(Controller, (512)&0xFF);
NF_ADDR(Controller, (512>>8)&0xFF);
NF_CMD(Controller, 0xE0);
#if NAND_TRANSFER_MODE == POLLING_TRANSFER
#if 0
for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) // MLC ECC Size : 512bytes
{
*pBuffer++ = NF_RDDATA8(Controller); // Read one page
}
#else
for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++)
{
*pBufferW++ = NF_RDDATA(Controller); // Read one page
}
#endif
#elif NAND_TRANSFER_MODE == DMA_TRANSFER
Nand_DmaDone = 0;
DMACH_Setup(DMA_A, 0x0, (u32)(&(NAND(Controller)->rNFDATA)), 1, (u32)pBufferW, 0, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, DMA1_NAND_TX, MEM, BURST128, &g_oNandDmac1);
DMACH_Start(&g_oNandDmac1);
while(!Nand_DmaDone);
pBufferW += NAND_MLC_TRANS_SIZE/4;
#endif
NF_CMD(Controller, 0x05);
NF_ADDR(Controller, (uPageSize+8)&0xFF);
NF_ADDR(Controller, ((uPageSize+8)>>8)&0xFF);
NF_CMD(Controller, 0xE0);
for(i=8;i<15;i++)
{
aNand_Spare_Data[i] = NF_RDDATA8(Controller);
if(NAND_Inform[Controller].uPerformanceCheck == 0)
*pSpareBuffer++ = aNand_Spare_Data[i];
}
while(g_Nand_4bitEccDecDone == 0);
eError = NAND_CheckECCError(Controller);
if(eError != eNAND_NoError)
{
NF_MECC_Lock(Controller);
NF_nFCE_H(Controller);
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp &= ~((1<<12)|(1<<13)); // 4bit ECC decoding Interrupt enable
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
NAND_Inform[Controller].uMLCECCPageReadSector = 1; //512 ~ 1023 Bytes
return eError;
}
//////////////////////////
// Read 1024 ~ 1535
//////////////////////////
g_Nand_4bitEccDecDone = 0;
NF_RSTECC(Controller); // Initialize ECC
#if (NAND_REG_BUG == TRUE)
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp |= (1<<12)|(1<<13); // 4bit ECC decoding/encoding Interrupt enable...because error
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -