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

📄 flash_util_func.c

📁 MTK手机平台下载工具FLASHTOOL驱动源码
💻 C
字号:
/*******************************************************************************
*  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) 2004
*
*******************************************************************************/

/*******************************************************************************
 *
 * Filename:
 * ---------
 *	 flash_util_func.c 
 *
 * Project:
 * --------
 *   FlashTool Download Agent 
 *
 * Description:
 * ------------
 *   Flash relative utility functions 
 *
 * Author:
 * -------
 *	 Amos Hsu 
 *
 *==============================================================================
 * 				HISTORY
 * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
 *------------------------------------------------------------------------------
 * $Revision:   1.5  $
 * $Modtime:   Oct 19 2005 11:09:04  $
 * $Log:   //mtkvs01/vmdata/flash_tool/archives/DA/SRC/flash_util_func.c-arc  $
 * 
 *    Rev 1.5   Oct 19 2005 14:45:16   mtk00539
 *  1. [BROM_DLL&DA][New] New H/W devices detection architecture including NOR, NAND, SRAM and DRAM detection. 
 *  2. [BROM_DLL&DA][New] DA partial download technic, that overcomes DA size exceeds MT6205B internal SRAM (32KB).
 *  3. [BROM_DLL&DA][New] Format verification option, each byte should be 0xFF after erasure. 
 *  4. [BROM_DLL&DA][New] DA validation to ensure invalid binary could not be loaded.
 *  5. [BROM_DLL&DA][New] Support NFB download. 
 *  6. [BROM_DLL&DA][New] Support NAND flash format with 3 method, NORMAL, FORCEDLY ERASE and MARK AS BAD BLOCK. 
 *  7. [BROM_DLL&DA][New] Support NAND flash read back with 4 methods, PAGE+ECC, PAGE ONLY, SPARE ONLY and PAGE+SPARE. 
 * Resolution for 140: [BROM_DLL v2.7.1008][New] Support NFB download and many new features.
 * 
 *    Rev 1.4   Jun 15 2005 12:41:52   mtk00539
 *  1. [DA][New] Support new flash devices TV0057A002AABD and TV0057A002AABD.
 *  2. [DA][New] Support RENESAS flash with F-WP#(LOW).
 * Resolution for 118: [BROM_DLL v2.4.1013][New] Support RENESAS flash with F-WP#(LOW).
 * 
 *    Rev 1.3   Nov 25 2004 09:49:22   mtk00539
 * [DA][Enhance] In order to speed-up the progress, only verify one time after erase.
 * Resolution for 99: [BROM_DLL v2.4.1008][New] Support INTEL family flash Buffered-Program method.
 * 
 *    Rev 1.2   Nov 22 2004 12:25:36   mtk00539
 *  1. [DA][BUG FIX] Add data verification in status polling during erase or program operation.
 *  2. [DA][BUG FIX] Fix two dies flash detection fail in INTEL_CheckDevID(). 
 *  3. [DA][Change Behavior] When RX_BUFFER_FULL occurs, flush data queued in UART ring buffer til data is less than 512KB.
 *  4. [DA][New] Support Buffered-Program method for INTEL family flashes.
 *  5. [DA][New] Support new flashes [SHARP]LRS1828C and [RENESAS]M6MGB64BM34CDG.
 * Resolution for 99: [BROM_DLL v2.4.1008][New] Support INTEL family flash Buffered-Program method.
 * 
 *    Rev 1.1   Aug 03 2004 10:33:06   mtk00539
 *  1. [DA][BUG FIX] Invoke Board_Schematic()(old name is HW_Init()) before FUTL_CheckDevice(). Because FUTL_CheckDevice() must know the absolute address for each bank.
 *  2. [DA][New] Add 12 new flash devices support 
 * 				[SAMSUNG]K5A3280YT,
 * 				[TOSHIBA]TH50VPF6782AASB,
 * 				[TOSHIBA]TH50VPF6783AASB,
 * 				[TOSHIBA]TV00578002AABD,
 * 				[TOSHIBA]TV00578003AABD,
 * 				[Fujitsu]MB84VP24581HK,
 * 				[INTEL]INTEL_28F640W30_B,
 * 				[SPANSION]AM49PDL127BH,
 * 				[SPANSION]AM49PDL129BH,
 * 				[RENESAS]M6MGD13BW66CDG,
 * 				[Winbond]W19B322TM,
 * 				[Winbond]W19B323TM,
 *  3. [DA][New] Readback check after WORD program is done, so that DA won't have to keep the chksum.
 *  4. [DA][New] Auto-detect baseband chip type.
 *  5. [DA][New] Auto-detect external SRAM size.
 *  6. [DA][New] Merge MT6205B, MT6218B and MT6219 to an all-in-one DA.
 *  7. [DA][New] Merge flash stress test module.
 *  8. [DA][New] Modify makefile to build ARM or THUMB code.
 *  9. [DA][New] Construct a customization kit for customers to add new flash or SOC checking algorithm by themselves.
 * 10. [DA][Enhance] Split out AM29PDL128G function to improve the performance of general AMD callback functions.
 * 11. [DA][Enhance] Enhance RX_BUFF_FULL behavior to prevent always retry two times.
 * Resolution for 83: [BROM_DLL v2.4.1002] Merge all the DAs into all-in-one DA and fix many bugs and enhancement.
 * 
 *    Rev 1.0   Jul 19 2004 01:44:40   mtk00539
 * Initial revision.
 * 
 *------------------------------------------------------------------------------
 * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
 *==============================================================================
 *******************************************************************************/
#include "flash_util_func.h"

uint16	g_FLASH_PGM_BUF[MAX_BUFPGM_SIZE_IN_WORD];
uint32	g_FLASH_MAX_BUFPGM_SIZE_IN_BYTE;
uint32	g_FLASH_CUR_PGM_COUNT;
uint32	g_FLASH_CUR_PGM_ADDR;
uint32	g_FLASH_LAST_PGM_COUNT;
uint32	g_FLASH_LAST_PGM_ADDR;

static bool FUTL_GetBaseAddrFromRegion(const uint32 addr, const uint16 die_num, const uint16 region, uint32 *blk_addr, uint32 *blk_size) {

//	volatile uint32 index;
//	volatile uint32 sector_baseaddr;
//	volatile uint32 die_baseaddr;
//	volatile uint32 region_baseaddr;
	uint32 index;
	uint32 sector_baseaddr;
	uint32 die_baseaddr;
	uint32 region_baseaddr;

	die_baseaddr = FUTL_GetFlashDieBaseAddr(die_num);
	region_baseaddr = die_baseaddr + REGION_BASE_OFFSET(g_FlashType, die_num, region);

	if( (addr < die_baseaddr) ||
		(addr >= (die_baseaddr+FLASH_DIE_SIZE(g_FlashType, die_num))) ||
		(addr >= (region_baseaddr+REGION_SIZE(g_FlashType, die_num, region)))
	) {
		return FALSE;
	}
	
	for(index=0; index<REGION_SECTOR_COUNT(g_FlashType, die_num, region); index++)	{
		sector_baseaddr = region_baseaddr + (index*REGION_SECTOR_SIZE(g_FlashType, die_num, region));
		if( (addr < (sector_baseaddr+REGION_SECTOR_SIZE(g_FlashType, die_num, region))) &&	(addr >= sector_baseaddr) )	{
			if( NULL != blk_addr ) {
				*blk_addr = sector_baseaddr;
			}
			if( NULL != blk_size ) {
				*blk_size = REGION_SECTOR_SIZE(g_FlashType, die_num, region);
			}
			return TRUE;
		}
	}
	
	return FALSE;
}

STATUS_E  FUTL_CheckDevice(void) {

	uint32 die1_addr;
	uint32 die2_addr;

	// search supported flash table 
	for(g_FlashType=0; NOR_UNKNOWN!=g_FlashDevTbl[g_FlashType].m_device_id; g_FlashType++)	{

		// get die1 addr 
		die1_addr = FUTL_GetFlashDieBaseAddr(0);

		// get die2 addr 
		if( 1 == FLASH_DIE_COUNT(g_FlashType) ) {
			die2_addr = die1_addr+FLASH_DIE_SIZE(g_FlashType,0);
		}
		else {
			die2_addr = FUTL_GetFlashDieBaseAddr(1);
		}

		if(g_FlashDevTbl[g_FlashType].m_cmd->m_cb_chk_dev_id(g_FlashType, (volatile uint16 *)die1_addr, (volatile uint16 *)die2_addr)) {
			// device found 
			break;
		}
	}

	if( NOR_UNKNOWN == g_FlashDevTbl[g_FlashType].m_device_id ) {
		return S_DEVICE_NOT_FOUND;
	}
	else {
		return S_DONE;
	}
}

bool FUTL_CheckRange(const uint32 start_addr, const uint32 length) {
	
//	volatile uint32	addr = start_addr;
//	volatile uint32	len = length;
//	volatile uint32	die_baseaddr;
	uint32	addr = start_addr;
	uint32	len = length;
	uint32	die_baseaddr;
	uint16	i;

	for(i=0; i<FLASH_DIE_COUNT(g_FlashType); i++) {
		
		die_baseaddr = FUTL_GetFlashDieBaseAddr(i);
		
		// check if addr locates in die(i) 
		if( addr>=die_baseaddr && addr<(die_baseaddr+FLASH_DIE_SIZE(g_FlashType, i)) ) {
			// check if len exceed die(i) range 
			if( len <= (die_baseaddr+FLASH_DIE_SIZE(g_FlashType, i)-addr) ) {
				// len doesn't exceed die(i) range, it's legal range 
				return TRUE;
			}
			else {
				// len exceed die(i) range, continue to match rest of len with next die 
				len -= (die_baseaddr+FLASH_DIE_SIZE(g_FlashType, i)-addr);
				addr = die_baseaddr+FLASH_DIE_SIZE(g_FlashType, i);
			}
		}
	}

	return FALSE;
}

bool FUTL_SearchBaseAddr(const uint32 addr, uint32 *blk_addr, uint32 *blk_size) {

//	volatile uint16 die_num;
//	volatile uint16 region;
	uint16 die_num;
	uint16 region;

	for(die_num=0; die_num<FLASH_DIE_COUNT(g_FlashType); die_num++) {
		for(region=0; region<MAX_SECTOR_REGION_PER_DIE; region++) {
			if(!IF_EMPTY_REGION(g_FlashType, die_num, region)) {
				if(FUTL_GetBaseAddrFromRegion(addr, die_num, region, blk_addr, blk_size)) {
					return TRUE;
				}
			}
		}
	}

	return FALSE;
}

uint32 FUTL_GetFlashDieBaseAddr(const uint16 die_num) {

	const uint32	addr = g_HW_DevCfg.m_storage_cfg.m_nor_baseaddr[die_num];
	
	if( NOR_UNKNOWN==g_FlashDevTbl[g_FlashType].m_device_id ||
		die_num>=FLASH_DIE_COUNT(g_FlashType)
	) {
		// error argument 
		while(1);
	}
	
	if( CS_WITH_DECODER != addr ) {
		// separate die address 
		return	addr;
	}
	else if( 0 < die_num ) {
		// continue die address, die(N) address is die(N-1) address plus die(N-1) size 
		return  (FUTL_GetFlashDieBaseAddr(die_num-1)+FLASH_DIE_SIZE(g_FlashType, die_num-1));
	}

	// error die layout 
	while(1);
}
				
uint32 FUTL_GetFlashSize(void) {

	uint16	i;
	uint32	flash_size = 0;

	if( NOR_UNKNOWN == g_FlashDevTbl[g_FlashType].m_device_id ) {
		return 0;
	}
	
	for(i=0, flash_size=0; i<FLASH_DIE_COUNT(g_FlashType); i++) {
		flash_size += FLASH_DIE_SIZE(g_FlashType, i);
	}

	return flash_size;
}

STATUS_E FUTL_EraseSector(const uint32 addr, const uint32 blk_size, bool bValidation) {
	STATUS_E	ret;
	CB_SECTOR_ERASE(g_FlashType, addr);
	while( S_IN_PROGRESS == (ret=FUTL_Erase_CheckDone(addr, blk_size, bValidation)) );
	return ret;
}

STATUS_E FUTL_Erase_CheckDone(const uint32 blockaddr, const uint32 blocksize, bool bValidation)
{
	volatile uint16		readback_1;
	volatile uint16		readback_2;
	uint32		status_check_retry;
	uint32		i;
	STATUS_E	ret;

	status_check_retry = 0;

check_status:

	// read status 
	ret = CB_SECTOR_ERASE_CHECK_DONE(g_FlashType, blockaddr);

	if( S_DONE == ret ) {
		// verify data 
		for(i=0; i<blocksize; i+=2) {
			readback_1 = *((volatile uint16 *)(blockaddr+i));
			readback_2 = *((volatile uint16 *)(blockaddr+i));
			if( (0xFFFF!=readback_1) || (0xFFFF!=readback_2) ) {
				if( MAX_STATUS_CHECK_RETRY <= (status_check_retry++) ) {
					return S_BLOCK_UNSTABLE;
				}
				else {
					goto check_status;
				}
			}
			if(!bValidation) {
				break;	// break loop, only check once! 
			}
		}
	}

	return ret;
}

STATUS_E FUTL_Program_CheckDone(const uint32 prog_addr, const uint16 verify_data)
{
	volatile uint16		*pa = (volatile uint16 *)prog_addr;
	volatile uint16		readback_1;
	volatile uint16		readback_2;
	uint32		status_check_retry;
	STATUS_E	ret;

	status_check_retry = 0;

check_status:	

	// read status 
	ret = CB_PROGRAM_CHECK_DONE(g_FlashType, prog_addr);

	if( S_DONE == ret ) {
		// verify data 
		readback_1 = *pa;
		readback_2 = *pa;
		if( (verify_data!=readback_1) || (verify_data!=readback_2) ) {
			if( MAX_STATUS_CHECK_RETRY <= (status_check_retry++) ) {
				return S_BLOCK_UNSTABLE;
			}
			else {
				goto check_status;
			}
		}
	}

	return ret;
}

STATUS_E FUTL_Buf_Program_CheckDone(const uint32 prog_addr, const uint16 *verify_data, const uint32 length_in_word)
{
	volatile uint16		*pa = (volatile uint16 *)prog_addr;
	volatile uint16		readback_1;
	volatile uint16		readback_2;
	volatile uint16		verify;
	uint32		status_check_retry;
	uint32		i;
	STATUS_E	ret;

	if(!BUFPGM_SUPPORT(g_FlashType)) {
		return S_BUFPGM_NO_SUPPORT;
	}

	status_check_retry = 0;

check_status:	

	// read status 
	ret = CB_BUF_PROGRAM_CHECK_DONE(g_FlashType, prog_addr);

	if( S_DONE == ret ) {
		// verify data 
		for(i=0; i<length_in_word; i++) {
			readback_1 = *((volatile uint16 *)(pa+i));
			readback_2 = *((volatile uint16 *)(pa+i));
			verify = verify_data[i];
			if( (verify!=readback_1) || (verify!=readback_2) ) {
				if( MAX_STATUS_CHECK_RETRY <= (status_check_retry++) ) {
					return S_BLOCK_UNSTABLE;
				}
				else {
					goto check_status;
				}
			}
		}
	}

	return ret;
}



⌨️ 快捷键说明

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