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

📄 nand_drv_common.c

📁 MTK手机平台下载工具FLASHTOOL驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	// read ECC parity info generated by NFI 
	// each parity register contains only 12 bits valid value 
	if( 512 < page_size ) {
		ecc_parity_from_reg[0] =  (*NFI_PAR0);
		ecc_parity_from_reg[0] |= (*NFI_PAR1) << 16;
		ecc_parity_from_reg[1] =  (*NFI_PAR2);
		ecc_parity_from_reg[1] |= (*NFI_PAR3) << 16;
		ecc_parity_from_reg[2] =  (*NFI_PAR4);
		ecc_parity_from_reg[2] |= (*NFI_PAR5) << 16;
		ecc_parity_from_reg[3] =  (*NFI_PAR6);
		ecc_parity_from_reg[3] |= (*NFI_PAR7) << 16;
	}
	else {
		// for 512 page size flash, the block-0 ECC parity are stored in PARITY6 and PARITY7 
		ecc_parity_from_reg[0] =  (*NFI_PAR6);
		ecc_parity_from_reg[0] |= (*NFI_PAR7) << 16;
		//ecc_parity_from_reg[1] = 0;
		//ecc_parity_from_reg[2] = 0;
		//ecc_parity_from_reg[3] = 0;
	}

end:
	// disable burst read 
	*NFI_OPCON = 0x0;

	return ret;
}

//------------------------------------------------------------------------------
// Page Program Callback Function                                               
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_PageProgram(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  c_timeout
				,const uint32  row_addr
				,const uint32 *p_data32 /* MUST be 32bits alignment addr */
				,uint32  ecc_parity_from_reg[4]
) {
	uint32		page_size;
	uint32		spare_size;
	uint32		column_addr_bits;
	uint32		addr_cycle;
	uint32		io_interface;
	STATUS_E	ret=S_UNKNOWN_ERR;
	bool		bUsingDMA=TRUE;

	page_size = NUTL_PAGE_SIZE(nand_info);
	spare_size = NUTL_SPARE_SIZE(nand_info);
	column_addr_bits = NUTL_PAGE_ADDR_SHIFT_BITS(nand_info);
	addr_cycle = NUTL_ADDR_CYCLE(nand_info);
	io_interface = NUTL_IO_INTERFACE(nand_info);

	// reset the NFI core state machine, data FIFO and flushing FIFO 
	*NFI_OPCON = 0x0;
	*NFI_CON = 0x0;
	*NFI_FIFOCON = 0x30;

	// in most 512 page size NAND flash, you have to setup destination pointer to 1st half area 
	if(nand_info->m_dev->m_cmd_set->m_program_1st_half_page.m_enable) {
		*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program_1st_half_page.m_cmd;
		// wait til CMD is completely issued 
		while( *NFI_PSTA & STATUS_CMD );
	}

	// program cmd 
	*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program.m_cmd;
	// wait til CMD is completely issued 
	while( *NFI_PSTA & STATUS_CMD );

	// fill 1~4 cycle addr 
	*NFI_ADDRL = (row_addr<<column_addr_bits);
	*NFI_ADDRM = 0;
	if( 4 < addr_cycle ) {
		// if addr cycle is more than 4, you have to fill 5th cycle addr 
		*NFI_ADDRM = (row_addr>>(32-column_addr_bits));
	}
	// no. of addr cycle 
	*NFI_ADDNOB = addr_cycle;
	// wait til ADDR is completely issued 
	while( *NFI_PSTA & STATUS_ADDR );


	// set burst program by DWORD 
	*NFI_OPCON = BURST_WR | NOB_DWORD;
	// wait til DATA_WRITE is completely issued 
	while( *NFI_PSTA & STATUS_DATAW );


#ifdef DISABLE_NFI_DMA
	bUsingDMA = FALSE;
#else
	bUsingDMA = TRUE;
	// activating DMA transfer 
	*NFI_CON |= DMA_WR_EN;
#endif

	// program page data 
	if( S_DONE != (ret=NUTL_FIFO_Write(c_timeout, bUsingDMA, p_data32, page_size)) ) {
		return ret;
	}
 
	// <<<<  WARNING!! >>>>                                                              
	// 1. You MUST read parity registers before issue program confirm (0x10) command.    
	//    Since the parity registers will be clean by NFI after issue program confirm.   
	// 2. You MUST wait until the NFI FIFO is empty!                                     
	//    It means all data in the FIFO had been written to NAND flash, and then you can 
	//    start to read ECC parity registers.                                            
	while(!(*NFI_FIFOCON & WR_EMPTY_MASK));

	// read ECC parity info generated by NFI 
	// each parity register contains only 12 bits valid value 
	if( 512 < page_size ) {
		ecc_parity_from_reg[0] =  (*NFI_PAR0);
		ecc_parity_from_reg[0] |= (*NFI_PAR1) << 16;
		ecc_parity_from_reg[1] =  (*NFI_PAR2);
		ecc_parity_from_reg[1] |= (*NFI_PAR3) << 16;
		ecc_parity_from_reg[2] =  (*NFI_PAR4);
		ecc_parity_from_reg[2] |= (*NFI_PAR5) << 16;
		ecc_parity_from_reg[3] =  (*NFI_PAR6);
		ecc_parity_from_reg[3] |= (*NFI_PAR7) << 16;
	}
	else {
		// for 512 page size flash, the block-0 ECC parity are stored in PARITY6 and PARITY7 
		ecc_parity_from_reg[0] =  (*NFI_PAR6);
		ecc_parity_from_reg[0] |= (*NFI_PAR7) << 16;
		//ecc_parity_from_reg[1] = 0;
		//ecc_parity_from_reg[2] = 0;
		//ecc_parity_from_reg[3] = 0;
	}	

	// program confirm 
	*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program_cnf.m_cmd;
	// wait til CMD is completely issued 
	while( *NFI_PSTA & STATUS_CMD );

	return S_DONE;
}

//------------------------------------------------------------------------------
// Spare Read Callback Function                                                 
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_SpareRead(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  c_timeout
				,const uint32  row_addr
				,uint32 *p_spare32 /* MUST be 32bits alignment addr */
) {
	uint32		page_size;
	uint32		spare_addr;
	uint32		spare_size;
	uint32		column_addr_bits;
	uint32		addr_cycle;
	uint32		io_interface;
	STATUS_E	ret=S_UNKNOWN_ERR;
	bool		bUsingDMA=TRUE;

	page_size = NUTL_PAGE_SIZE(nand_info);
	spare_size = NUTL_SPARE_SIZE(nand_info);
	column_addr_bits = NUTL_PAGE_ADDR_SHIFT_BITS(nand_info);
	addr_cycle = NUTL_ADDR_CYCLE(nand_info);
	io_interface = NUTL_IO_INTERFACE(nand_info);

	// reset the NFI core state machine, data FIFO and flushing FIFO 
	*NFI_OPCON = 0x0;
	*NFI_CON = 0x0;
	*NFI_FIFOCON = 0x30;

	// set NFI core to write/read spare area 
	*NFI_CON = SW_PROGSPARE_EN;

	// set up spare address 
	if( 512 < page_size ) {
		// plus the page size to set the column address to the beginning of spare area 
		if( NAND_IO_16BITS == io_interface ) {
			// for 16 bits I/O, the address is WORD address, so the offset to the spare area should be page_size/2 
			spare_addr = (row_addr<<column_addr_bits)+(page_size>>1); 
		}
		else {
			spare_addr = (row_addr<<column_addr_bits)+page_size; 
		}
	}
	else {
		// set up spare address, A7-A4 don't care, A3-A0 is the offset whthin the spare area 
		spare_addr = (row_addr<<column_addr_bits);
	}

	// read cmd 
	if(nand_info->m_dev->m_cmd_set->m_read_spare.m_enable) {
		// in most 512 page size NAND flash, you have to setup destination pointer to spare area 
		*NFI_CMD = nand_info->m_dev->m_cmd_set->m_read_spare.m_cmd;
	}
	else {
		*NFI_CMD = nand_info->m_dev->m_cmd_set->m_read.m_cmd;
	}
	// wait til CMD is completely issued 
	while( *NFI_PSTA & STATUS_CMD );

	// fill 1~4 cycle addr 
	*NFI_ADDRL = spare_addr;
	*NFI_ADDRM = 0;
	if( 4 < addr_cycle ) {
		// if addr cycle is more than 4, you have to fill 5th cycle addr 
		*NFI_ADDRM = (row_addr>>(32-column_addr_bits));
	}
	// no. of addr cycle 
	*NFI_ADDNOB = addr_cycle;
	// wait til ADDR is completely issued 
	while( *NFI_PSTA & STATUS_ADDR );


	// read confirm 
	if(nand_info->m_dev->m_cmd_set->m_read_cnf.m_enable) {
		*NFI_CMD = nand_info->m_dev->m_cmd_set->m_read_cnf.m_cmd;
	}
	// set burst read by DWORD 
	*NFI_OPCON = BURST_RD | NOB_DWORD;
	// wait til DATA_READ is completely issued 
	while( *NFI_PSTA & STATUS_DATAR );


#ifdef DISABLE_NFI_DMA
	bUsingDMA = FALSE;
#else
	bUsingDMA = TRUE;
	// activating DMA transfer 
	*NFI_CON |= DMA_RD_EN;
#endif

	// read spare data 
	if( S_DONE != (ret=NUTL_FIFO_Read(c_timeout, bUsingDMA, p_spare32, spare_size)) ) {
		goto end;
	}

end:
	// disable burst read 
	*NFI_OPCON = 0x0;

	return ret;
}

//------------------------------------------------------------------------------
// Spare Program Callback Function                                              
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_SpareProgram(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  c_timeout
				,const uint32  row_addr
				,const uint32 *p_spare32 /* MUST be 32bits alignment addr */
) {
	uint32		page_size;
	uint32		spare_addr;
	uint32		spare_size;
	uint32		column_addr_bits;
	uint32		addr_cycle;
	uint32		io_interface;
	uint32		timeout = c_timeout;
	STATUS_E	ret=S_UNKNOWN_ERR;
	bool		bUsingDMA=TRUE;

	page_size = NUTL_PAGE_SIZE(nand_info);
	spare_size = NUTL_SPARE_SIZE(nand_info);
	column_addr_bits = NUTL_PAGE_ADDR_SHIFT_BITS(nand_info);
	addr_cycle = NUTL_ADDR_CYCLE(nand_info);
	io_interface = NUTL_IO_INTERFACE(nand_info);

	// reset the NFI core state machine, data FIFO and flushing FIFO 
	*NFI_OPCON = 0x0;
	*NFI_CON = 0x0;
	*NFI_FIFOCON = 0x30;

	// set NFI core to write/read spare area 
	*NFI_CON = SW_PROGSPARE_EN;

	// set up spare address 
	if(nand_info->m_dev->m_cmd_set->m_read_spare.m_enable) {
		// in most 512 page size NAND flash, you have to setup destination pointer to spare area 
		*NFI_CMD = nand_info->m_dev->m_cmd_set->m_read_spare.m_cmd;
		// wait til CMD is completely issued 
		while( *NFI_PSTA & STATUS_CMD );

		// set up spare address, A7-A4 don't care, A3-A0 is the offset whthin the spare area 
		spare_addr = (row_addr<<column_addr_bits);
	}
	else {
		// if no additional spare cmd is required, just plus the page size to set the column address to the beginning of spare area 
		if( NAND_IO_16BITS == io_interface ) {
			// for 16 bits I/O, the address is WORD address, so the offset to the spare area should be page_size/2 
			spare_addr = (row_addr<<column_addr_bits)+(page_size>>1); 
		}
		else {
			spare_addr = (row_addr<<column_addr_bits)+page_size; 
		}
	}

	// program cmd 
	*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program.m_cmd;
	// wait til CMD is completely issued 
	while( *NFI_PSTA & STATUS_CMD );

	// fill 1~4 cycle addr 
	*NFI_ADDRL = spare_addr;
	*NFI_ADDRM = 0;
	if( 4 < addr_cycle ) {
		// if addr cycle is more than 4, you have to fill 5th cycle addr 
		*NFI_ADDRM = (row_addr>>(32-column_addr_bits));
	}
	// no. of addr cycle 
	*NFI_ADDNOB = addr_cycle;
	// wait til ADDR is completely issued 
	while( *NFI_PSTA & STATUS_ADDR );

	// set burst program by DWORD 
	*NFI_OPCON = BURST_WR | NOB_DWORD;
	// wait til DATA_WRITE is completely issued 
	while( *NFI_PSTA & STATUS_DATAW );

#ifdef DISABLE_NFI_DMA
	bUsingDMA = FALSE;
#else
	bUsingDMA = TRUE;
	// activating DMA transfer 
	*NFI_CON |= DMA_WR_EN;
#endif

	// program spare data 
	if( S_DONE != (ret=NUTL_FIFO_Write(c_timeout, bUsingDMA, p_spare32, spare_size)) ) {
		return ret;
	}

	// <<<<  WARNING!! >>>>                                                              
	// 1. You MUST wait until the NFI FIFO is empty!                                     
	//    It means all data in the FIFO had been written to NAND flash.                  
	timeout = c_timeout;
	NFI_Wait( !(*NFI_FIFOCON & WR_EMPTY_MASK), timeout);
	if( 0 == timeout ) {
		return S_TIMEOUT;
	}

	// program confirm 
	*NFI_CMD = nand_info->m_dev->m_cmd_set->m_program_cnf.m_cmd;
	// wait til CMD is completely issued 
	while( *NFI_PSTA & STATUS_CMD );

	return S_DONE;
}

//------------------------------------------------------------------------------
// CopyBack Callback Function                                                   
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_CopyBack(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  c_timeout
				,const uint32  src_row_addr
				,const uint32  dest_row_addr
) {
	uint32	page_size;
	uint32	spare_size;
	uint32	column_addr_bits;
	uint32	addr_cycle;
	uint32	io_interface;
	uint32	timeout = c_timeout;
	STATUS_E	ret=S_UNKNOWN_ERR;

	page_size = NUTL_PAGE_SIZE(nand_info);
	spare_size = NUTL_SPARE_SIZE(nand_info);
	column_addr_bits = NUTL_PAGE_ADDR_SHIFT_BITS(nand_info);
	addr_cycle = NUTL_ADDR_CYCLE(nand_info);
	io_interface = NUTL_IO_INTERFACE(nand_info);

	// reset the NFI core state machine, data FIFO and flushing FIFO 
	*NFI_OPCON = 0x0;
	*NFI_CON = 0x0;
	*NFI_FIFOCON = 0x30;

	// enable interrupt 
	*NFI_INTR_EN = BUSY_RETURN_EN;

	// copyback read cmd 
	*NFI_CMD = nand_info->m_dev->m_cmd_set->m_copyback_read.m_cmd;
	// wait til CMD is completely issued 
	while( *NFI_PSTA & STATUS_CMD );

	// fill 1~4 cycle addr 
	*NFI_ADDRL = (src_row_addr<<column_addr_bits);
	*NFI_ADDRM = 0;
	if( 4 < addr_cycle ) {
		// if addr cycle is more than 4, you have to fill 5th cycle addr 
		*NFI_ADDRM = (src_row_addr>>(32-column_addr_bits));
	}
	// no. of addr cycle 
	*NFI_ADDNOB = addr_cycle;
	// wait til ADDR is completely issued 
	while( *NFI_PSTA & STATUS_ADDR );

	// copyback read confirm 
	if(nand_info->m_dev->m_cmd_set->m_copyback_read_cnf.m_enable) {
		*NFI_CMD = nand_info->m_dev->m_cmd_set->m_copyback_read_cnf.m_cmd;
		// wait til CMD is completely issued 
		while( *NFI_PSTA & STATUS_CMD );
	}

	// wait for copyback read finish 
	timeout = c_timeout;
	NFI_Wait( !(*NFI_INTR & BUSY_RETURN), timeout);
	if( 0 == timeout ) {
		ret = S_TIMEOUT;
		goto end;
	}

	// copyback program cmd 
	*NFI_CMD = nand_info->m_dev->m_cmd_set->m_copyback_program.m_cmd;
	// wait til CMD is completely issued 
	while( *NFI_PSTA & STATUS_CMD );

	// fill 1~4 cycle addr 
	*NFI_ADDRL = (dest_row_addr<<column_addr_bits);
	*NFI_ADDRM = 0;
	if( 4 < addr_cycle ) {
		// if addr cycle is more than 4, you have to fill 5th cycle addr 
		*NFI_ADDRM = (dest_row_addr>>(32-column_addr_bits));
	}
	// no. of addr cycle 
	*NFI_ADDNOB = addr_cycle;
	// wait til ADDR is completely issued 
	while( *NFI_PSTA & STATUS_ADDR );

	// copy-back program confirm 
	if(nand_info->m_dev->m_cmd_set->m_copyback_program_cnf.m_enable) {
		*NFI_CMD = nand_info->m_dev->m_cmd_set->m_copyback_program_cnf.m_cmd;
		// wait til CMD is completely issued 
		while( *NFI_PSTA & STATUS_CMD );
	}

//	while( *NFI_PSTA & STATUS_BUSY );
/*
	// wait for copyback program finish 
	timeout = c_timeout;
	NFI_Wait( !(*NFI_INTR & BUSY_RETURN), timeout) {
		if( 1 == timeout ) {
			if( S_IN_PROGRESS != (ret=CB_NAND_READ_STATUS(nand_info, c_timeout)) ) {
				UART_Printf("NO BUSY_RETURN, ret=(%d)\r\n", ret);
			}
		}
	}
	if( 0 == timeout ) {
		ret = S_TIMEOUT;
		goto end;
	}*/

	ret = S_DONE;

end:
	// disable interrupt 
	*NFI_INTR_EN = 0;

	return ret;
}

⌨️ 快捷键说明

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