📄 flash_util_func.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 + -