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

📄 nand.c

📁 s3c6410基于USB OTG下载内核至NORFLASH的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	NF_CMD(Controller, 0x80);	// 1st Write 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_TRANSFER_MODE == POLLING_TRANSFER
	#if 0
		for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) 	// MLC ECC Size : 512bytes
		{
			NF_WRDATA8(Controller, *pBuffer++);		// Write one page
		}
	#else
		for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++) 
		{
			NF_WRDATA(Controller, *pBufferW++);	// Write one page
		}
	#endif
	#elif NAND_TRANSFER_MODE == DMA_TRANSFER
		Nand_DmaDone = 0;
		DMACH_Setup(DMA_A, 0x0, (u32)pBufferW, 0, (u32)(&(NAND(Controller)->rNFDATA)), 1, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, MEM, DMA1_NAND_RX, BURST128, &g_oNandDmac1);
			
		DMACH_Start(&g_oNandDmac1);
		while(!Nand_DmaDone);	
	   	pBufferW += NAND_MLC_TRANS_SIZE/4;
	#endif

	//NF_MECC_Lock(Controller);

	while(!g_Nand_4bitEccEncDone);

	uMecc0 = Inp32(&(NAND(Controller)->rNFMECC0));
	uMecc1 = Inp32(&(NAND(Controller)->rNFMECC1)) & 0xFFFFFF;

	aNand_Spare_Data[1]=(u8)(uMecc0&0xff);
	aNand_Spare_Data[2]=(u8)((uMecc0>>8) & 0xff);
	aNand_Spare_Data[3]=(u8)((uMecc0>>16) & 0xff);
	aNand_Spare_Data[4]=(u8)((uMecc0>>24) & 0xff);
	aNand_Spare_Data[5]=(u8)(uMecc1&0xff);
	aNand_Spare_Data[6]=(u8)((uMecc1>>8) & 0xff);
	aNand_Spare_Data[7]=(u8)((uMecc1>>16) & 0xff);	

	//////////////////////////
	// Write 512 ~ 1023
	//////////////////////////
	g_Nand_4bitEccEncDone = 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

#if NAND_TRANSFER_MODE == POLLING_TRANSFER
	#if 0
		for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) 	// MLC ECC Size : 512bytes
		{
			NF_WRDATA8(Controller, *pBuffer++);		// Write one page
		}
	#else
		for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++) 
		{
			NF_WRDATA(Controller, *pBufferW++);	// Write one page
		}
	#endif
	#elif NAND_TRANSFER_MODE == DMA_TRANSFER
		Nand_DmaDone = 0;
		DMACH_Setup(DMA_A, 0x0, (u32)pBufferW, 0, (u32)(&(NAND(Controller)->rNFDATA)), 1, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, MEM, DMA1_NAND_RX, BURST128, &g_oNandDmac1);
			
		DMACH_Start(&g_oNandDmac1);
		while(!Nand_DmaDone);	
	   	pBufferW += NAND_MLC_TRANS_SIZE/4;
	#endif

	while(!g_Nand_4bitEccEncDone);

	uMecc0 = Inp32(&(NAND(Controller)->rNFMECC0));
	uMecc1 = Inp32(&(NAND(Controller)->rNFMECC1)) & 0xFFFFFF;

	aNand_Spare_Data[8]=(u8)(uMecc0&0xff);
	aNand_Spare_Data[9]=(u8)((uMecc0>>8) & 0xff);
	aNand_Spare_Data[10]=(u8)((uMecc0>>16) & 0xff);
	aNand_Spare_Data[11]=(u8)((uMecc0>>24) & 0xff);
	aNand_Spare_Data[12]=(u8)(uMecc1&0xff);
	aNand_Spare_Data[13]=(u8)((uMecc1>>8) & 0xff);
	aNand_Spare_Data[14]=(u8)((uMecc1>>16) & 0xff);
	
	//////////////////////////
	// Write 1024 ~ 1535
	//////////////////////////
	g_Nand_4bitEccEncDone = 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

#if NAND_TRANSFER_MODE == POLLING_TRANSFER
	#if 0
		for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) 	// MLC ECC Size : 512bytes
		{
			NF_WRDATA8(Controller, *pBuffer++);		// Write one page
		}
	#else
		for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++) 
		{
			NF_WRDATA(Controller, *pBufferW++);	// Write one page
		}
	#endif
	#elif NAND_TRANSFER_MODE == DMA_TRANSFER
		Nand_DmaDone = 0;
		DMACH_Setup(DMA_A, 0x0, (u32)pBufferW, 0, (u32)(&(NAND(Controller)->rNFDATA)), 1, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, MEM, DMA1_NAND_RX, BURST128, &g_oNandDmac1);
			
		DMACH_Start(&g_oNandDmac1);
		while(!Nand_DmaDone);	
	   	pBufferW += NAND_MLC_TRANS_SIZE/4;
	#endif

	while(!g_Nand_4bitEccEncDone);

	uMecc0 = Inp32(&(NAND(Controller)->rNFMECC0));
	uMecc1 = Inp32(&(NAND(Controller)->rNFMECC1)) & 0xFFFFFF;

	aNand_Spare_Data[15]=(u8)(uMecc0&0xff);
	aNand_Spare_Data[16]=(u8)((uMecc0>>8) & 0xff);
	aNand_Spare_Data[17]=(u8)((uMecc0>>16) & 0xff);
	aNand_Spare_Data[18]=(u8)((uMecc0>>24) & 0xff);
	aNand_Spare_Data[19]=(u8)(uMecc1&0xff);
	aNand_Spare_Data[20]=(u8)((uMecc1>>8) & 0xff);
	aNand_Spare_Data[21]=(u8)((uMecc1>>16) & 0xff);
	
	//////////////////////////
	// Write 1536 ~ 2047
	//////////////////////////
	g_Nand_4bitEccEncDone = 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

#if NAND_TRANSFER_MODE == POLLING_TRANSFER
	#if 0
		for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) 	// MLC ECC Size : 512bytes
		{
			NF_WRDATA8(Controller, *pBuffer++);		// Write one page
		}
	#else
		for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++) 
		{
			NF_WRDATA(Controller, *pBufferW++);	// Write one page
		}
	#endif
	#elif NAND_TRANSFER_MODE == DMA_TRANSFER
		Nand_DmaDone = 0;
		DMACH_Setup(DMA_A, 0x0, (u32)pBufferW, 0, (u32)(&(NAND(Controller)->rNFDATA)), 1, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, MEM, DMA1_NAND_RX, BURST128, &g_oNandDmac1);
			
		DMACH_Start(&g_oNandDmac1);
		while(!Nand_DmaDone);	
	   	pBufferW += NAND_MLC_TRANS_SIZE/4;
	#endif

	while(!g_Nand_4bitEccEncDone);

	uMecc0 = Inp32(&(NAND(Controller)->rNFMECC0));
	uMecc1 = Inp32(&(NAND(Controller)->rNFMECC1)) & 0xFFFFFF;

	aNand_Spare_Data[22]=(u8)(uMecc0&0xff);
	aNand_Spare_Data[23]=(u8)((uMecc0>>8) & 0xff);
	aNand_Spare_Data[24]=(u8)((uMecc0>>16) & 0xff);
	aNand_Spare_Data[25]=(u8)((uMecc0>>24) & 0xff);
	aNand_Spare_Data[26]=(u8)(uMecc1&0xff);
	aNand_Spare_Data[27]=(u8)((uMecc1>>8) & 0xff);
	aNand_Spare_Data[28]=(u8)((uMecc1>>16) & 0xff);

	//////////////////////////
	// Spare Area Write
	//////////////////////////
	
	for(i=0 ; i<uSpareSize ; i++)
		NF_WRDATA8(Controller, aNand_Spare_Data[i]);

	NF_CMD(Controller, 0x10);	// 2nd Write Command

	while(!g_Nand_RnBTransition)
	{
		if(g_Nand_IllegalAccError == 1)
		{
			NAND_Reset(Controller);
			g_Nand_IllegalAccError = 0;
			return eNAND_ProgramError;
		}
	}
	
	//Read Program Status
	NF_CMD(Controller, 0x70);

	while(!((uStatus = NF_RDDATA8(Controller)) & (1<<6)));
	if(uStatus & 0x01)
		eError = eNAND_ProgramError;		// Error in Program
	else
		eError = eNAND_NoError;

	NF_nFCE_H(Controller);
	
	uTemp = NAND_ReadNFCONRegister(Controller);
	uTemp &= ~((1<<13)|(1<<12)|(1<<10)|(1<<9));		// 4bit ECC encoding & Illegal Access & RnB Transition Interrupt disable
	Outp32(&(NAND(Controller)->rNFCONT), uTemp);

	if(NAND_Inform[Controller].uPerformanceCheck == 0)
	{
		if(NAND_Inform[Controller].uECCtest == 1)
		{
			for(i=0 ; i<uSpareSize ; i++)
				aNand_Spare_Data_Temp[i] = aNand_Spare_Data[i];
		}

		for(i=0 ; i<uSpareSize ; i++)
			*aSpareBuffer++ = aNand_Spare_Data[i];
	}
	
	INTC_Disable(NUM_NFC);
	
	return eError;
}


//////////
// Function Name : NAND_WritePage
// Function Description : This function write the 1 page data of external MLC Type NAND device
// Input : 	Controller - Nand Controller Port Number 
//			uBlock - Write Block
//			uPage - Write Page
//			pBuffer - Write data buffer
// Output : 	Nand Error Type
NAND_eERROR NAND_WritePage(u32 Controller, u32 uBlock, u32 uPage, u8 *pBuffer, u8 *aSpareBuffer)
{
	NAND_eERROR eError;

	if( (NAND_Inform[Controller].uNandType == NAND_Normal8bit) || (NAND_Inform[Controller].uNandType == NAND_Advanced8bit) )
		eError = NAND_WritePageSLC(Controller, uBlock, uPage, pBuffer, aSpareBuffer);
	else //if(NAND_Inform[Controller].uNandType == NAND_MLC8bit)
		eError = NAND_WritePageMLC(Controller, uBlock, uPage, pBuffer, aSpareBuffer);

	return eError;
}


//////////
// Function Name : NAND_EraseSingleBlock
// Function Description : This function erase 1 block data
// Input : 	Controller - Nand Controller Port Number 
//			uBlock - Erase Block
// Output : 	Nand Error Type
NAND_eERROR NAND_EraseSingleBlock(u32 Controller, u32 uBlock)
{
	u32 uTemp, uBlockPage, uStatus;
	NAND_eERROR eError;

	if(NAND_Inform[Controller].uNandType == NAND_Normal8bit)
	{
		uBlockPage=(uBlock<<5);
	}
	else if(NAND_Inform[Controller].uNandType == NAND_Advanced8bit)
	{
		uBlockPage=(uBlock<<6);
	}
	else //if(NAND_Inform[Controller].uNandType == NAND_MLC8bit)
	{
		uBlockPage=(uBlock<<7);
	}

	uTemp = NAND_ReadNFCONRegister(Controller);
	uTemp |= (1<<10) | (1<<9);		// Illegal Access & RnB Transition Interrupt enable
	Outp32(&(NAND(Controller)->rNFCONT), uTemp);
	
	Outp32(&(NAND(Controller)->rNFSTAT), (1<<5)|(1<<4));		// Illegal Access & RnB Interrupt Pending bit clear
	INTC_Enable(NUM_NFC);

	//Invalid Block Check
	eError = NAND_CheckInvalidBlock(Controller, uBlockPage);
	if(eError != eNAND_NoError)
		return eError;

	g_Nand_RnBTransition = 0;
	g_Nand_IllegalAccError = 0;

	NF_nFCE_L(Controller);
	NF_CLEAR_RnB(Controller);

	NF_CMD(Controller, 0x60);					// 1st Erase Command

	NF_ADDR(Controller, uBlockPage&0xff);	 		// The mark of bad block is in 0 page
	NF_ADDR(Controller, (uBlockPage>>8)&0xff);	 	// For block number A[24:17]
	NF_ADDR(Controller, (uBlockPage>>16)&0xff);  		// For block number A[25]

	NF_CMD(Controller, 0xd0);								// 2nd Erase command

	while(!g_Nand_RnBTransition)
	{
		if(g_Nand_IllegalAccError == 1)
		{
			NAND_Reset(Controller);
			g_Nand_IllegalAccError = 0;
			return eNAND_EraseError;
		}
	}

	NF_CMD(Controller, 0x70);   // Read status command

	while(!((uStatus = NF_RDDATA8(Controller)) & (1<<6)));
	if(uStatus & 0x01)
		eError = eNAND_EraseError;		// Error in Program
	else
		eError = eNAND_NoError;
	
//      if (NF_RDDATA8(Controller)&0x1) // Erase error check
//		eError = eNAND_EraseError;
//       else 
//		eError = eNAND_NoError;
	   
	NF_nFCE_H(Controller);

	uTemp = NAND_ReadNFCONRegister(Controller);
	uTemp &= ~((1<<10)|(1<<9));		// Illegal Access & RnB Transition Interrupt disable
	Outp32(&(NAND(Controller)->rNFCONT), uTemp);

	// rb1004 : must be modify...Interrupt Controller
	//INT_Disable1(BIT_INT_NFC);
	INTC_Disable(NUM_NFC);
	
	return eError;
}


//////////
// Function Name : NAND_EraseMultiBlock
// Function Description : This function erase the multi-block data
// Input : 	Controller - Nand Controller Port Number 
//			uBlock - Erase Block
//			uBlockNum - Erase Block Number
// Output : 	Nand Error Type
NAND_eERROR NAND_EraseMultiBlock(u32 Controller, u32 uBlock, u32 uBlockNum)
{
	u32 i, j, uMultiEraseNum, uTemp, uStatus;
	u32 uBlockShift, uBlockPage;
	NAND_eERROR eError;
	
	eError = eNAND_NoError;
	
	if(NAND_Inform[Controller].uNandType == NAND_Normal8bit)
	{
		uBlockPage=(uBlock<<5);
		uBlockShift = 5;
		uMultiEraseNum = 4;
	}
	else if(NAND_Inform[Controller].uNandType == NAND_Advanced8bit)
	{
		uBlockPage=(uBlock<<6);
		uBlockShift = 6;		
		uMultiEraseNum = 2;
	}
	else //if(NAND_Inform[Controller].uNandType == NAND_MLC8bit)
	{
		uBlockPage=(uBlock<<7);
		uBlockShift = 7;		
		uMultiEraseNum = 2;
	}

	uTemp = NAND_ReadNFCONRegister(Controller);
	uTemp |= (1<<10) | (1<<9);		// Illegal Access & RnB Transition Interrupt enable
	Outp32(&(NAND(Controller)->rNFCONT), uTemp);
	
	Outp32(&(NAND(Controller)->rNFSTAT), (1<<5)|(1<<4));		// Illegal Access & RnB Interrupt Pending bit clear
	INTC_Enable(NUM_NFC);	

	//Invalid Block Check
	for(i=uBlock ; i<(uBlock+uBlockNum-1) ; i++)
	{
		eError = NAND_CheckInvalidBlock(Controller, i);
		if(eError != eNAND_NoError)
			return eError;
	}

	for(i=0 ; i<uBlockNum ; i+=uMultiEraseNum )
	{
		g_Nand_RnBTransition = 0;
		g_Nand_IllegalAccError = 0;
		
		NF_nFCE_L(Controller);
		NF_CLEAR_RnB(Controller);

		for(j=0 ; j<uMultiEraseNum ; j++)
		{
			NF_CMD(Controller, 0x60);						// 1st Erase Command

			NF_ADDR(Controller, uBlockPage&0xff);	 		
			NF_ADDR(Controller, (uBlockPage>>8)&0xff);	 	
			NF_ADDR(Controller, (uBlockPage>>16)&0xff);  	
			uBlockPage += (1<<uBlockShift);
		}

		NF_CMD(Controller, 0xd0);							// 2nd Erase command

		while(!g_Nand_RnBTransition)
		{
			if(g_Nand_IllegalAccError == 1)
			{
				NAND_Reset(Controller);
				g_Nand_IllegalAccError = 0;
				NF_nFCE_H(Controller);
				uTemp = NAND_ReadNFCONRegister(Controller);
				uTemp &= ~((1<<10)|(1<<9));		// Illegal Access & RnB Transition Interrupt disable
				Outp32(&(NAND(Controller)->rNFCONT), uTemp);

				INTC_Disable(NUM_NFC);				
				return eNAND_EraseError;

⌨️ 快捷键说明

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