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

📄 nand_drv_common.c

📁 MTK手机平台下载工具FLASHTOOL驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
*  Copyright Statement:
*  --------------------
*  This software is protected by Copyright and the information contained
*  herein is confidential. The software may not be copied and the information
*  contained herein may not be used or disclosed except with the written
*  permission of MediaTek Inc. (C) 2005
*
*******************************************************************************/

/*******************************************************************************
 *
 * Filename:
 * ---------
 *	 nand_drv_COMMON.c 
 *
 * Project:
 * --------
 *   FlashTool Download Agent 
 *
 * Description:
 * ------------
 *   General NAND flash driver compatible with most of SAMSUNG devices. 
 *
 * Author:
 * -------
 *	 Amos Hsu 
 *
 *==============================================================================
 * 				HISTORY
 * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
 *------------------------------------------------------------------------------
 * $Revision:   1.1  $
 * $Modtime:   Dec 19 2005 15:41:24  $
 * $Log:   //mtkvs01/vmdata/new_flash_tool/archives/DA/SRC/nand_drv_COMMON.c-arc  $
 *
 * Feb 23 2006 mtk00539
 * [STP100000625] FlashTool v2.7.1016
 * 
 * 
 *    Rev 1.1   Dec 29 2005 10:53:18   mtk00539
 *  1. [DA] Add pre-process callback function to unlock all the blocks to meet ST NAND flash requirement. 
 * Resolution for 156: [FlashTool v2.7.1013][BUG FIX] Fix BootROM start command failure while manually selecting NMT6226 or MT6227 baseband chip.
 * 
 *    Rev 1.0   Oct 19 2005 14:41:06   mtk00539
 * Initial revision.
 * Resolution for 140: [BROM_DLL v2.7.1008][New] Support NFB download and many new features.
 * 
 *------------------------------------------------------------------------------
 * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
 *==============================================================================
 *******************************************************************************/
#include "nand_drv_COMMON.h"
#include "nand_util_func.h"
#include "NFI.h"

//------------------------------------------------------------------------------
// COMMON Callback Function Set                                                 
//------------------------------------------------------------------------------
const NAND_CMD_Callback_S	g_NAND_COMMON_CB_FUNC_SET={
	NAND_COMMON_ReadID
	,NAND_COMMON_Reset
	,NULL
	,NAND_COMMON_ReadStatus
	,NAND_COMMON_BlockErase
	,NAND_COMMON_BadBlockSymbol_Check
	,NAND_COMMON_BadBlockSymbol_Set
	,NAND_COMMON_PageRead
	,NAND_COMMON_PageProgram
	,NAND_COMMON_SpareRead
	,NAND_COMMON_SpareProgram
	,NAND_COMMON_CopyBack
};

//------------------------------------------------------------------------------
// COMMON Callback Function Set Without H/W CopyBack Function                   
//------------------------------------------------------------------------------
const NAND_CMD_Callback_S	g_NAND_COMMON_CB_FUNC_SET_WITHOUT_COPYBACK={
	NAND_COMMON_ReadID
	,NAND_COMMON_Reset
	,NULL
	,NAND_COMMON_ReadStatus
	,NAND_COMMON_BlockErase
	,NAND_COMMON_BadBlockSymbol_Check
	,NAND_COMMON_BadBlockSymbol_Set
	,NAND_COMMON_PageRead
	,NAND_COMMON_PageProgram
	,NAND_COMMON_SpareRead
	,NAND_COMMON_SpareProgram
	,NULL
};

//------------------------------------------------------------------------------
// Read Device ID Callback Function                                             
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_ReadID(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  c_timeout
				,uint16	*p_maker_code
				,uint16	*p_device_code
				,uint16 *p_ext_code1
				,uint16 *p_ext_code2
) {
	uint32	id1 = 0;
	uint16	nfi_pagefmt;
	STATUS_E	ret=S_UNKNOWN_ERR;

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

	// always use 8bits I/O interface to read device id 
	nfi_pagefmt = *NFI_PAGEFMT;
	*NFI_PAGEFMT = nfi_pagefmt&(~PAGEFMT_16BITS)|PAGEFMT_8BITS;

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

	// issue addr 
	*NFI_ADDRL = 0;
	*NFI_ADDNOB = 1;
	// wait til ADDR is completely issued 
	while( *NFI_PSTA & STATUS_ADDR );

	// set single read by DWORD 
	*NFI_OPCON = SINGLE_RD | NOB_DWORD;
	// wait til DATA_READ is completely issued 
	while( *NFI_PSTA & STATUS_DATAR );

	// single read doesn't need to polling FIFO 
	id1 = *NFI_DATAR;

	*p_maker_code = (id1&0xFF);
	*p_device_code = ((id1>>8)&0xFF);
	*p_ext_code1 = ((id1>>16)&0xFF);
	*p_ext_code2 = ((id1>>24)&0xFF);

	ret = S_DONE;

	// restore original page format setting 
	*NFI_PAGEFMT = nfi_pagefmt;

	return ret;
}

//------------------------------------------------------------------------------
// Reset Device Callback Function                                               
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_Reset(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  c_timeout
) {
	uint32		timeout = c_timeout;
	STATUS_E	ret=S_UNKNOWN_ERR;

	// 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;

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

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

	ret = S_DONE;

end:
	// disable interrupt 
	*NFI_INTR_EN = 0;

	return ret;
}

//------------------------------------------------------------------------------
// Read Status Callback Function                                                
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_ReadStatus(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  c_timeout
) {
	uint32	status;

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

	// set single read by DWORD 
	*NFI_OPCON = SINGLE_RD | NOB_DWORD;
	// wait til DATA_READ is completely issued 
	while( *NFI_PSTA & STATUS_DATAR );

	// single read doesn't need to polling FIFO 
	status = *NFI_DATAR;

	// check READY/BUSY status first 
	if( !(STATUS_READY&status) ) {
		return S_IN_PROGRESS;
	}

	// flash is ready now, check status code 
	if( STATUS_FAIL & status ) {
		if( !(STATUS_WR_ALLOW&status) ) {
			return S_BLOCK_LOCKED_ERR;
		}
		else {
			return S_UNKNOWN_ERR;
		}
	}
	else {
		return S_DONE;
	}
}

//------------------------------------------------------------------------------
// Block Erase Related Callback Function                                        
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_BlockErase(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  row_addr
) {
	uint32	page_size;
	uint32	spare_size;
	uint32	addr_cycle;

	page_size = NUTL_PAGE_SIZE(nand_info);
	spare_size = NUTL_SPARE_SIZE(nand_info);
	addr_cycle = NUTL_ADDR_CYCLE(nand_info);

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

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

	// fill 1~4 cycle addr, erase command only fill row address, so column bits shift is unnecessary 
	*NFI_ADDRL = row_addr;
	*NFI_ADDRM = 0;
	// no. of addr cycle 
	if( 512 < page_size ) {
		*NFI_ADDNOB = addr_cycle-2;
	}
	else {
		*NFI_ADDNOB = addr_cycle-1;
	}
	// wait til ADDR is completely issued 
	while( *NFI_PSTA & STATUS_ADDR );

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

	return S_DONE;
}

//------------------------------------------------------------------------------
// Bad Block Symbol Identification Related Callback Function                    
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_BadBlockSymbol_Check(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  *p_spare32 /* MUST be 32bits alignment addr */
) {
	uint32	page_size;
	uint32	spare_size;
	uint32	column_addr_bits;
	uint32	addr_cycle;
	uint32	io_interface;
	const uint8		*p_spare8 = (const uint8 *)p_spare32;
	const uint16	*p_spare16 = (const uint16 *)p_spare32;

	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);

	// check the invalid block status from spare area 
	if( 512 < page_size ) {
		// for 2048 page size flash, the invalid block status is defined by the 1st byte/word in spare area 
		if( NAND_IO_16BITS == io_interface ) {
			if( 0xFFFF != p_spare16[0] ) {
				return S_BAD_BLOCK;
			}
		}
		else {
			if( 0xFF != p_spare8[0] ) {
				return S_BAD_BLOCK;
			}
		}
	}
	else {
		// for 512 page size flash 
		if( NAND_IO_16BITS == io_interface ) {
#if 0
			// for 16 bits I/O, the invalid block status is defined by the 1st and 6th word in spare area 
			if( 0xFFFF!=p_spare16[0] || 0xFFFF!=p_spare16[5] ) {
#else
			// for 16 bits I/O, the invalid block status is defined by the 1st word in spare area 
			if( 0xFFFF != p_spare16[0] ) {
#endif
				return S_BAD_BLOCK;
			}
		}
		else {
			// for 8 bits I/O, the invalid block status is defined by the 6th byte in spare area 
			if( 0xFF != p_spare8[5] ) {
				return S_BAD_BLOCK;
			}
		}
	}

	return S_DONE;
}

STATUS_E  NAND_COMMON_BadBlockSymbol_Set(
				const NAND_DeviceInfo_S  *nand_info
				,uint32  *p_spare32 /* MUST be 32bits alignment addr */
) {
	uint32	page_size;
	uint32	spare_size;
	uint32	io_interface;
	uint8	*p_spare8 = (uint8 *)p_spare32;
	uint16	*p_spare16 = (uint16 *)p_spare32;
	uint32	i;

	page_size = NUTL_PAGE_SIZE(nand_info);
	spare_size = NUTL_SPARE_SIZE(nand_info);
	io_interface = NUTL_IO_INTERFACE(nand_info);

	// reset spare 
	for(i=0; i<(spare_size>>2); i++) {
		p_spare32[i] = 0xAAAAAAAA;
	}

	// check the invalid block status from spare area 
	if( 512 < page_size ) {
		// for 2048 page size flash, the invalid block status is defined by the 1st byte/word in spare area 
		if( NAND_IO_16BITS == io_interface ) {
			p_spare16[0] = 0x0;
		}
		else {
			p_spare8[0] = 0x0;
		}
	}
	else {
		// for 512 page size flash 
		if( NAND_IO_16BITS == io_interface ) {
#if 0
			// for 16 bits I/O, the invalid block status is defined by the 1st and 6th word in spare area 
			p_spare16[0] = 0x0;
			p_spare16[5] = 0x0;
#else
			// for 16 bits I/O, the invalid block status is defined by the 1st word in spare area 
			p_spare16[0] = 0x0;
#endif
		}
		else {
			// for 8 bits I/O, the invalid block status is defined by the 6th byte in spare area 
			p_spare8[5] = 0x0;
		}
	}

	return S_DONE;
}

//------------------------------------------------------------------------------
// Page Read Callback Function                                                  
//------------------------------------------------------------------------------
STATUS_E  NAND_COMMON_PageRead(
				const NAND_DeviceInfo_S  *nand_info
				,const uint32  c_timeout
				,const uint32  row_addr
				,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;
	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);

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

	// read cmd 
	*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 = (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 );


	// 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 page data 
	if( S_DONE != (ret=NUTL_FIFO_Read(c_timeout, bUsingDMA, p_data32, page_size)) ) {
		goto end;
	}

	// <<<<  WARNING!! >>>>                                                               
	// 1. You MUST wait until the NFI FIFO is empty.                                      
	//    It means all data in the FIFO had been read out, and then you can start to read 
	//    ECC parity registers.                                                           
	while(!(*NFI_FIFOCON & RD_EMPTY_MASK));

⌨️ 快捷键说明

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