⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nand.c

📁 s3c6410基于USB OTG下载内核至NORFLASH的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		{
			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

	NF_CMD(Controller, 0x05);
	NF_ADDR(Controller, (512*2)&0xFF);
	NF_ADDR(Controller, ((512*2)>>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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -