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

📄 nand_mtd.c

📁 8032底层驱动部分。因为可以移植 所以单独来拿出来
💻 C
📖 第 1 页 / 共 5 页
字号:
		return FS_NO_ERROR;

}	/*  End of ProgramSpare_2K */


/*******************************************************************************/
int ReadSpare_2K(void * DriveData, DWORD PageIndex, BYTE * Data)	//need modification
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status, cs;


	pdn_nfi(1);

#ifdef _NAND_FLASH_BOOTING_
	PageIndex += NFB_FLASH_BASE_PAGE;
#endif

	if((PageIndex < NANDSUBDriveData[1].base_page) || (NANDSUBDriveData[1].base_page==0)  )		// chip select 0
	{
		cs = 0;
		SET_NFI_CS0;
	}
	else		// chip select 1
	{
		cs = 1;
		SET_NFI_CS1;
	}


	if (NANDSUBDriveData[cs].io_width == IO_ACCESS_8BIT)
	{
		*NFI_PAGEFMT = PAGEFMT_2K_8BIT;
	}
   else
   {
		*NFI_PAGEFMT = PAGEFMT_2K_16BIT;

		#if ((defined(MT6228)) || (defined(MT6229) ))
			*NFI_GPIO_DATA1 &= 0x0FFF;
			*NFI_GPIO_DATA2 &= 0xF000;
		#endif
	}

	D->flash_info.address_cycle = NANDSUBDriveData[cs].address_cycle;
	D->flash_info.io_width = NANDSUBDriveData[cs].io_width;
	status = NANDSUBDriveData[cs].sub_driver->ReadSpare(D, (PageIndex-NANDSUBDriveData[cs].base_page), Data);

	if(cs)
		SET_NFI_CS1_END;

	*NFI_OPCON = 0;
	pdn_nfi(0);

	if( status == FS_DATA_ERROR )
		return FS_DATA_ERROR;
	else
		return FS_NO_ERROR;

} /*  End of ReadSpare_2K */

#ifdef PAGE_COPY_SUPPORT
/*******************************************************************************/
int CopyPage_via_MCU(void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint32 status;
	status = NANDFlashMtd.ReadPage(DriveData, SrcPageIndex, (kal_uint8 *)mtd_buffer, (kal_uint8 *)mtd_spare, 1, ECC_WHOLE);
	/* TODO: handle read failure */
	//if( status != FS_NO_ERROR )//at least one bit correction is done.
	//	return FS_DATA_ERROR;
	status = NANDFlashMtd.ProgramPage(DriveData, DestPageIndex, (kal_uint8 *)mtd_buffer, (kal_uint8 *)mtd_spare, ECC_WHOLE);
	if( status != FS_NO_ERROR )
		return FS_DATA_ERROR;
} /*  End of CopyPage_via_MCU */

/*******************************************************************************/
int CopyPermitted_default(void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
	if( ((SrcPageIndex < NANDSUBDriveData[1].base_page) && (DestPageIndex >= NANDSUBDriveData[1].base_page)) ||
	    ((DestPageIndex < NANDSUBDriveData[1].base_page) && (SrcPageIndex >= NANDSUBDriveData[1].base_page)) )
	{
		return 0;//in different chips
	}
	return 1;
}

int CopyPermitted_Samsung(void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint32 cs = 0, plane_mask = 0;
	kal_uint32 src_blk = 0, dest_blk = 0;

	/* page copy back can be performed only within same plane and with same position attribute, i.e.
	 * even to even or odd to odd.
	 */

	if((SrcPageIndex & 0x01) != (DestPageIndex & 0x01))
		return 0;

	if( ((SrcPageIndex < NANDSUBDriveData[1].base_page) && (DestPageIndex >= NANDSUBDriveData[1].base_page)) ||
	    ((DestPageIndex < NANDSUBDriveData[1].base_page) && (SrcPageIndex >= NANDSUBDriveData[1].base_page)) )
	{
		return 0;/* src page and dest page are in different chips*/
	}
	if((SrcPageIndex < NANDSUBDriveData[1].base_page) || (NANDSUBDriveData[1].base_page==0))// chip select 0
	{
		cs = 0; // chip select 0
	}
	else
	{
		cs = 1; // chip select 1
	}
	
	/* both pages are in the same plane? */
	src_blk = (SrcPageIndex - NANDSUBDriveData[cs].base_page)/(NANDSUBDriveData[cs].pages_per_block);
	dest_blk = (DestPageIndex - NANDSUBDriveData[cs].base_page)/(NANDSUBDriveData[cs].pages_per_block);
	plane_mask = NANDSUBDriveData[cs].plane_mask;
	if( (src_blk & plane_mask) != (dest_blk & plane_mask) )
		return 0;

	return 1;
}

int CopyPage_2K (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status, cs;

	/* page copy back can be performed only within same plane and with same position attribute, i.e.
	 * even to even or odd to odd.
	 */
	#ifdef _NAND_FLASH_BOOTING_
	if(( (SrcPageIndex+NFB_FLASH_BASE_PAGE) < NANDSUBDriveData[1].base_page) 
	    || (NANDSUBDriveData[1].base_page==0)) // chip select 0
	#else
	if((SrcPageIndex < NANDSUBDriveData[1].base_page) || (NANDSUBDriveData[1].base_page==0)) // chip select 0
	#endif
	{
		cs = 0;
	}
	else
	{
		cs = 1;
	}

	/* In case that one device has copy back support and the other does not under dual NAND condition */
	if( NANDSUBDriveData[cs].sub_driver->CopyPermitted )
	{
	#ifdef _NAND_FLASH_BOOTING_
	if( !NANDSUBDriveData[cs].sub_driver->CopyPermitted(DriveData, SrcPageIndex+NFB_FLASH_BASE_PAGE, DestPageIndex+NFB_FLASH_BASE_PAGE) )
	#else
	if( !NANDSUBDriveData[cs].sub_driver->CopyPermitted(DriveData, SrcPageIndex, DestPageIndex) )
	#endif
		return CopyPage_via_MCU(DriveData, SrcPageIndex, DestPageIndex);
	}
	else
		return CopyPage_via_MCU(DriveData, SrcPageIndex, DestPageIndex);

	D->flash_info.address_cycle = NANDSUBDriveData[cs].address_cycle;
	D->flash_info.io_width = NANDSUBDriveData[cs].io_width;
	/* read src page data via NFI to ensure that data content is ECC verified. -- kirk
	 */
	if(NANDSUBDriveData[cs].sub_driver->CopyPage)
	{
		if( MTD_STATUS_CORRECTED != NANDFlashMtd.ReadPage(DriveData, SrcPageIndex, (kal_uint8 *)mtd_buffer, (kal_uint8 *)mtd_spare, 1, ECC_WHOLE) )
		{
			pdn_nfi(1);
			if( 0 == cs ) // chip select 1
			{
				SET_NFI_CS0;
			}
			else // chip select 1
			{
				SET_NFI_CS1;
			}

			if (NANDSUBDriveData[cs].io_width == IO_ACCESS_8BIT)
			{
				*NFI_PAGEFMT = PAGEFMT_2K_8BIT;
			}
			else
			{
				*NFI_PAGEFMT = PAGEFMT_2K_16BIT;

				#if ((defined(MT6228)) || (defined(MT6229) ))
					*NFI_GPIO_DATA1 &= 0x0FFF;
					*NFI_GPIO_DATA2 &= 0xF000;
				#endif
			}
			#ifdef _NAND_FLASH_BOOTING_
			status = NANDSUBDriveData[cs].sub_driver->CopyPage(D, (SrcPageIndex+NFB_FLASH_BASE_PAGE-NANDSUBDriveData[cs].base_page), 
			                                                   (DestPageIndex+NFB_FLASH_BASE_PAGE-NANDSUBDriveData[cs].base_page));
			#else
			status = NANDSUBDriveData[cs].sub_driver->CopyPage(D, (SrcPageIndex-NANDSUBDriveData[cs].base_page), 
			                                                   (DestPageIndex-NANDSUBDriveData[cs].base_page));
			#endif
			mtd_copy_counts++;
			if(cs)
				SET_NFI_CS1_END;

			*NFI_OPCON = 0;
			pdn_nfi(0);

		}
		else// data has been ECC corrected.
			status = NANDFlashMtd.ProgramPage(DriveData, DestPageIndex, (kal_uint8 *)mtd_buffer, (kal_uint8 *)mtd_spare, ECC_WHOLE);
	}
	else
		EXT_ASSERT(0, (kal_uint32)NANDFlashMtd.CopyPage, (kal_uint32)NANDSUBDriveData[cs].sub_driver->CopyPermitted, 0);//should not happen.

	if( status == FS_DATA_ERROR )
		return FS_DATA_ERROR;
	else
		return FS_NO_ERROR;
} /*  End of CopyPage_2K */

/*******************************************************************************/
int CopyPage_2K_default (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status = 0, nfi_pst = 0;
	kal_uint32 event_group;

	//cmd_resetpointer();
	*NFI_FIFOCON = RESET;
	*NFI_OPCON = 0;
	*NFI_CON = 0;

	//if (nfi_egid != 0 && use_interrupt == KAL_TRUE)
	//	*NFI_INTR_EN = BUSY_RETURN_EN;//WR_COMPLETE_EN;

	*NFI_CMD = RD_1ST_CMD; // Issue read command
	while (*NFI_PSTA & STATUS_CMD);	
	*NFI_ADDRL = SrcPageIndex << 16; // source address stage
	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = SrcPageIndex >> 16;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);
	
	*NFI_CMD = CP_READ_CMD; // Issue copy read command
	while (*NFI_PSTA & STATUS_CMD);

	while (*NFI_PSTA & STATUS_BUSY);//wait for data to be copied to data cache from data buffer
	//if (nfi_egid && use_interrupt == KAL_TRUE)
	//{
	//	kal_retrieve_eg_events(nfi_egid, NFI_EVENT, KAL_OR_CONSUME,
	//								  &event_group, KAL_SUSPEND);
	//}

	if (nfi_egid && use_interrupt == KAL_TRUE)
	  *NFI_INTR_EN = BUSY_RETURN_EN;

	*NFI_CMD = CP_INPUT_CMD_2K; // Issue copy data command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = DestPageIndex << 16; // destination address stage
	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = DestPageIndex >> 16;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	//if (nfi_egid && use_interrupt == KAL_TRUE)
	//  *NFI_INTR_EN = BUSY_RETURN_EN;
	*NFI_CMD = PROG_DATA_CMD;		// Issue program command
	while (*NFI_PSTA & STATUS_CMD);

	if (nfi_egid && use_interrupt == KAL_TRUE)
	{
		kal_retrieve_eg_events(nfi_egid, NFI_EVENT, KAL_OR_CONSUME,
									  &event_group, KAL_SUSPEND);
	}
	else
	{
		// using interrupt instead of polling after system initialization and before exception in normal mode
		if(nfi_egid && (kal_query_systemInit() == KAL_FALSE && INT_QueryExceptionStatus() == KAL_FALSE))
			use_interrupt = KAL_TRUE;
	}

	//while (*NFI_PSTA & STATUS_BUSY);
	//while (!((status = read_cp_status())&RDY_BUSY));
	while (!((status = read_status())&RDY_BUSY));
	*NFI_OPCON = 0;

	if (status&PASS_FAIL)
		return FS_DATA_ERROR;

	return FS_NO_ERROR;
} /*  End of CopyPage_2K_default */

int CopyPage_512_Samsung (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status = 0, nfi_pst = 0;
	kal_uint32 event_group;

	cmd_resetpointer();
	*NFI_OPCON = 0;
	*NFI_FIFOCON = RESET;
	*NFI_CON = 0;

	*NFI_CMD = RD_1ST_CMD; // Issue read command
	while (*NFI_PSTA & STATUS_CMD);	
	*NFI_ADDRL = SrcPageIndex << 8; // source address stage
	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = SrcPageIndex >> 24;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	while (*NFI_PSTA & STATUS_BUSY);//wait for data to be copied to data cache from data buffer

	if (nfi_egid && use_interrupt == KAL_TRUE)
	  *NFI_INTR_EN = BUSY_RETURN_EN;

	*NFI_CMD = CP_INPUT_CMD_512; // Issue copy data command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = DestPageIndex << 8; // destination address stage
	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = DestPageIndex >> 24;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_CMD = PROG_DATA_CMD;		// Issue program command
	while (*NFI_PSTA & STATUS_CMD);

	if (nfi_egid && use_interrupt == KAL_TRUE)
	{
		kal_retrieve_eg_events(nfi_egid, NFI_EVENT, KAL_OR_CONSUME,
									  &event_group, KAL_SUSPEND);
	}
	else
	{
		// using interrupt instead of polling after system initialization and before exception in normal mode
		if(nfi_egid && (kal_query_systemInit() == KAL_FALSE && INT_QueryExceptionStatus() == KAL_FALSE))
			use_interrupt = KAL_TRUE;
	}

	while (!((status = read_status())&RDY_BUSY));
	*NFI_OPCON = 0;

	if (status&PASS_FAIL)
		return FS_DATA_ERROR;

	return FS_NO_ERROR;
} /*  End of CopyPage_512_Samsung */

int CopyPage_2K_Toshiba (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
	return FS_NO_ERROR;
}

int CopyPage_2K_test (void * DriveData, DWORD SrcPageIndex, DWORD DestPageIndex)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status = 0, nfi_pst = 0;
	kal_uint32 event_group;

	*NFI_OPCON = 0;
	*NFI_FIFOCON = RESET;
	*NFI_CON = 0;

	*NFI_CMD = RD_1ST_CMD; // Issue read command
	while (*NFI_PSTA & STATUS_CMD);	
	*NFI_ADDRL = SrcPageIndex << 16; // source address stage
	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = SrcPageIndex >> 16;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);
#if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#else
	*NFI_CMD = CP_READ_CMD; // Issue copy read command
	while (*NFI_PSTA & STATUS_CMD);

	while (*NFI_PSTA & STATUS_BUSY);//wait for data to be copied to data cache from data buffer
#endif

	if (nfi_egid && use_interrupt == KAL_TRUE)
	  *NFI_INTR_EN = BUSY_RETURN_EN;

	*NFI_CMD = CP_INPUT_CMD_2K; // Issue copy data command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = DestPageIndex << 16; // destination address stage
	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = DestPageIndex >> 16;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_CMD = PROG_DATA_CMD;		// Issue program command
	while (*NFI_PSTA & STATUS_CMD);

	if (nfi_egid && use_interrupt == KAL_TRUE)
	{
		kal_retrieve_eg_events(nfi_egid, NFI_EVENT, KAL_OR_CONSUME,
									  &event_group, KAL_SUSPEND);
	}
	else
	{
		// using interrupt instead of polling after system initialization and before exception in normal mode
		if(nfi_egid && (kal_query_systemInit() == KAL_FALSE && INT_QueryExceptionStatus() == KAL_FALSE))
			use_interrupt = KAL_TRUE;
	}

	while (!((status = read_cp_status())&RDY_BUSY));
	*NFI_OPCON = 0;

	if (status&PASS_FAIL)
		return FS_DATA_ERROR;

	return FS_NO_ERROR;
} /*  End of CopyPage_2K_test */
#endif //PAGE_COPY_SUPPORT

/*******************************************************************************
 *  512 page-size MTD sub functions for default device
 *******************************************************************************/

int ProgramPage_512_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE ECCFlag)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status;


	cmd_resetpointer();

	if (nfi_egid != 0 && use_interrupt == KAL_TRUE)
		*NFI_INTR_EN = WR_COMPLETE_EN;

	*NFI_CON = SW_PROGSPARE_EN;
	*NFI_CMD = INPUT_DATA_CMD;					// Issue data input command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = PageIndex << 8;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_OPCON = BURST_WR;						// set burst write

	writefifo_512((kal_uint32*)Data, (kal_uint32*)Spare, ECCFlag, 128);

	while (!((status = read_status())&RDY_BUSY));
	*NFI_OPCON = 0;

	if (status&PASS_FAIL)
		return FS_DATA_ERROR;

	return FS_NO_ERROR;

} /*  End of ProgramPage_512 */

/*******************************************************************************/

int ReadPage_512_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE SpareFlag, BYTE ECCFlag)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint32 *mybuffer = (kal_uint32 *)Data;
	kal_uint16 error_detect, sym0_address;      // for ECC detection/correct
	kal_uint32 sym0_data;
	kal_int32  status = 0;


	/* NFI setting */
	*NFI_FIFOCON = RESET;
   *NFI_CON = AUTOECC_DEC_EN;	  				// for NFI ECC decoding
	*NFI_CMD = RD_1ST_CMD;						// read command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = PageIndex << 8;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// number of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_OPCON = BURST_RD;						// set burst read

⌨️ 快捷键说明

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