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

📄 flash_drv_amd.c

📁 MTK手机平台下载工具FLASHTOOL驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:

	{
		 { 0x00000000,	31,		0x40000 }
		,{ 0x007C0000,	4,		0x10000 }
		,{ 0, 0, 0 }
		,{ 0, 0, 0 }
	}
};

// MirrorBit Top/Bottom Boot 
const NOR_Die_Layout_S		AMD_MB_TB_128 = {

	0x01000000,

	{
		 { 0x00000000,	4,		0x10000 }
		,{ 0x00040000,	62,		0x40000 }
		,{ 0x00FC0000,	4,		0x10000 }
		,{ 0, 0, 0 }
	}
};

const NOR_Die_Layout_S		AMD_MB_TB_256 = {

	0x02000000,

	{
		 { 0x00000000,	4,		0x10000 }
		,{ 0x00040000,	126,    0x40000 }
		,{ 0x01FC0000,	4,		0x10000 }
		,{ 0, 0, 0 }
	}
};

//------------------------------------------------------------------------------
// Check Device ID Callback Function                                            
//------------------------------------------------------------------------------
bool AMD_CheckDevID(const uint16 dev, volatile uint16 *die1_addr, volatile uint16 *die2_addr) {
	//                                                                                     
	// Some 128Mb flash devices were assembled by two the same 64Mb flash devices.         
	// The worse thing is that the 128Mb flash share the same manufacture id and device    
	// code with 64Mb flash !!!                                                            
	//                                                                                     
	// For example:                                                                        
	//    AM50DL128CG(128Mb) was assembled by two AM29DL640D(64Mb) devices.                
	//    S71JL128HXX(128Mb) was assembled by two S29JL064HXX(64Mb) devices.               
	//    ST_M74DW66500B(128Mb) was assembled by two ST_M29DW640D(64Mb) devices.           
	//                                                                                     
	// This function has ability to tell from those flashes that share the same id.        
	//                                                                                     
	uint16	manufacture_code;
	uint16	dev_code;
	uint16	ext_dev_code1;
	uint16	ext_dev_code2;
	uint16	die_count = 0;
	uint16	ADDR_LEFT_SHIFT_BIT = 0;
	uint16	boot_sector_flag;
	uint16	cfi_bank_a_region_info;
	NOR_DeviceID_E	flash_enum_id=g_FlashDevTbl[dev].m_device_id;

	// check if AM29PDL128G 
	if( NOR_AM29PDL128G == flash_enum_id ) {
		ADDR_LEFT_SHIFT_BIT = 1;
	}

	// reset die1 to read mode 
	die1_addr[AMD_SA_ADDR<<ADDR_LEFT_SHIFT_BIT] = AMD_RESET_TO_READ_MODE_DATA1;

	// identify AM49DL3208GT or S29PL032J by reading CFI boot sector flag, because these two flashes has the same ID 
	if(	(NOR_AM49DL3208GT == flash_enum_id) ||
		(NOR_S29PL032J == flash_enum_id) 
	) {
		// enter CFI mode 
		die1_addr[AMD_ENTER_CFI_ADDR<<ADDR_LEFT_SHIFT_BIT] = AMD_ENTER_CFI_DATA;
		// read Top/Bottom Boot Sector Flag 
		boot_sector_flag = die1_addr[AMD_CFI_BOOT_SECTOR_FLAG_ADDR<<ADDR_LEFT_SHIFT_BIT];
		// reset die1 to read mode 
		die1_addr[AMD_SA_ADDR<<ADDR_LEFT_SHIFT_BIT] = AMD_RESET_TO_READ_MODE_DATA1;
		// check if boot sector is matched 
		if( ((&AMD_T_32)==FLASH_DIE_LAYOUT(dev, 0) && AMD_CFI_TOP_DEV!=boot_sector_flag) ||
			((&AMD_B_32)==FLASH_DIE_LAYOUT(dev, 0) && AMD_CFI_BOTTOM_DEV!=boot_sector_flag) 
		) {
			return FALSE;
		}
	}

	// identify S71PLXXXJ and S71PLXXXN(MirrorBit) by reading CFI Bank A region info, because those devices have the same ID 
	switch(flash_enum_id) {
	case NOR_AM49PDL127BH:
	case NOR_S71PL254J:
	case NOR_AM49PDL129BH:
	case NOR_S71PL127N:
	case NOR_S71PL129N:
		// enter CFI mode 
		die1_addr[AMD_ENTER_CFI_ADDR<<ADDR_LEFT_SHIFT_BIT] = AMD_ENTER_CFI_DATA;
		// read bank A region info 
		cfi_bank_a_region_info = die1_addr[AMD_CFI_BANK_A_REGION_INFO_ADDR<<ADDR_LEFT_SHIFT_BIT];
		// reset die1 to read mode 
		die1_addr[AMD_SA_ADDR<<ADDR_LEFT_SHIFT_BIT] = AMD_RESET_TO_READ_MODE_DATA1;
		// check if region info match 
		if( ( (NOR_S71PL127N==flash_enum_id || NOR_S71PL129N==flash_enum_id) && 0x000B!=cfi_bank_a_region_info) ||
			(!(NOR_S71PL127N==flash_enum_id || NOR_S71PL129N==flash_enum_id) && 0x000B==cfi_bank_a_region_info)
		) {
			return FALSE;
		}
		break;
	default:
		break;
	}

	// enter auto-select mode on die1 
	die1_addr[AMD_CMD_ADDR1<<ADDR_LEFT_SHIFT_BIT] = AMD_ENTER_AUTOSELECT_MODE_DATA1;
	die1_addr[AMD_CMD_ADDR2<<ADDR_LEFT_SHIFT_BIT] = AMD_ENTER_AUTOSELECT_MODE_DATA2;
	die1_addr[AMD_CMD_ADDR1<<ADDR_LEFT_SHIFT_BIT] = AMD_ENTER_AUTOSELECT_MODE_DATA3;

	// read manufacture id and device code from die1 
	manufacture_code = (die1_addr[AMD_MANUFACTURE_ID_ADDR<<ADDR_LEFT_SHIFT_BIT]&0x00FF);	dev_code = die1_addr[AMD_DEVICE_CODE_ADDR<<ADDR_LEFT_SHIFT_BIT];
	ext_dev_code1 = die1_addr[AMD_EXT_DEVICE_CODE1_ADDR<<ADDR_LEFT_SHIFT_BIT];
	ext_dev_code2 = die1_addr[AMD_EXT_DEVICE_CODE2_ADDR<<ADDR_LEFT_SHIFT_BIT];

	// compare id 
	if( g_FlashDevTbl[dev].m_hw_info.m_manufacture_code != manufacture_code )
		goto not_match;

	// if manufacture code exist, temporarily record flash id to g_HW_DetectionResult 
	g_HW_DetectionResult.m_flash_dev_code_1 = manufacture_code;
	g_HW_DetectionResult.m_flash_dev_code_2 = dev_code;
	g_HW_DetectionResult.m_flash_dev_code_3 = ext_dev_code1;
	g_HW_DetectionResult.m_flash_dev_code_4 = ext_dev_code2;

	if( g_FlashDevTbl[dev].m_hw_info.m_dev_code != dev_code )
		goto not_match;
	if( 0!=g_FlashDevTbl[dev].m_hw_info.m_ext_dev_code1 && (g_FlashDevTbl[dev].m_hw_info.m_ext_dev_code1!=ext_dev_code1) )
		goto not_match;
	if( 0!=g_FlashDevTbl[dev].m_hw_info.m_ext_dev_code2 && (g_FlashDevTbl[dev].m_hw_info.m_ext_dev_code2!=ext_dev_code2) )
		goto not_match;

	// die1 id matched, continue to check if this flash is dual stack 
	if( 0 != memcmp((void *)die1_addr, (void *)die2_addr, 64) ) {
		// if it's dual stack, the 2nd die baseaddr won't enter auto-select mode, 
		// the data locate in die1 and die2 address won't be the same. 
		die_count = 2;
	}
	else {
		// otherwise the 2nd baseaddr will enter auto-select mode due to address wrap, 
		// the data locate in die1 and die2 address will be the same. 
		die_count = 1;
	}

	// reset die1 to read mode 
	die1_addr[AMD_SA_ADDR<<ADDR_LEFT_SHIFT_BIT] = AMD_RESET_TO_READ_MODE_DATA1;

	// if die count matched, return true 
	if( die_count == FLASH_DIE_COUNT(dev) ) {
		return TRUE;
	}

not_match:

	// reset die1 to read mode 
	die1_addr[AMD_SA_ADDR<<ADDR_LEFT_SHIFT_BIT] = AMD_RESET_TO_READ_MODE_DATA1;

	return FALSE;
}

//------------------------------------------------------------------------------
// Check If Device Is Idle Callback Function                                    
//------------------------------------------------------------------------------
bool AMD_CheckDevIdle(const uint32 addr)
{
	volatile uint16 stat_data1;
	volatile uint16 stat_data2;
	
	stat_data1 = *(volatile uint16*)addr;
	stat_data2 = *(volatile uint16*)addr;
	
	if( (stat_data1&AMD_DQ6_TOGGLE_BIT) == (stat_data2&AMD_DQ6_TOGGLE_BIT) )
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

//------------------------------------------------------------------------------
// Erase Related Callback Function                                              
//------------------------------------------------------------------------------
void AMD_Erase_CMD(const uint32 blockaddr)
{
	volatile uint16 *ba = (volatile uint16 *)blockaddr;
	
	ba[AMD_CMD_ADDR1] = AMD_SECTOR_ERASE_DATA1;
	ba[AMD_CMD_ADDR2] = AMD_SECTOR_ERASE_DATA2;
	ba[AMD_CMD_ADDR1] = AMD_SECTOR_ERASE_DATA3;
	ba[AMD_CMD_ADDR1] = AMD_SECTOR_ERASE_DATA4;
	ba[AMD_CMD_ADDR2] = AMD_SECTOR_ERASE_DATA5;
	ba[AMD_SA_ADDR] = AMD_SECTOR_ERASE_DATA6;
}

STATUS_E AMD_Erase_CheckDone_By_Polling(const uint32 blockaddr)
{
	// use POLL_BIT instead of TOGGLE_BIT to wait for erase complete, 
	// because in some device using TOGGLE_BIT to wait for erase complete will fail. 
	volatile uint16 status;

	status = *(volatile uint16 *)blockaddr;
	if( (status&AMD_DQ7_POLL_BIT) ) {
		return S_DONE;
	}
	else if( (status&AMD_DQ5_TIMEOUT_ERR_BIT) ) {
		status = *(volatile uint16 *)blockaddr;
		if( (status&AMD_DQ7_POLL_BIT) ) {
			return S_DONE;
		}
		else {
			return S_TIMEOUT;
		}
	}
	else {
		return S_IN_PROGRESS;
	}
}

//------------------------------------------------------------------------------
// Program Related Callback Function                                            
//------------------------------------------------------------------------------
void AMD_PreProcess(const uint16 dev) {
#ifdef AMD_PROTECTION_ENABLED
	AMD_UnprotectChip(dev);
#endif
}

void AMD_UnlockBypass_Enter_CMD(const uint32 blockaddr)
{
	volatile uint16 *ba = (volatile uint16 *)blockaddr;
	
	ba[AMD_CMD_ADDR1] = AMD_ENTER_UNLOCK_BYPASS_DATA1;
	ba[AMD_CMD_ADDR2] = AMD_ENTER_UNLOCK_BYPASS_DATA2;
	ba[AMD_CMD_ADDR1] = AMD_ENTER_UNLOCK_BYPASS_DATA3;
}

void AMD_UnlockBypass_Exit_CMD(const uint32 blockaddr)
{
	volatile uint16 *ba = (volatile uint16 *)blockaddr;
	
	ba[AMD_CMD_ADDR1] = AMD_EXIT_UNLOCK_BYPASS_DATA1;
	ba[AMD_CMD_ADDR2] = AMD_EXIT_UNLOCK_BYPASS_DATA2;
}

void AMD_UnlockBypass_Program_CMD(const uint32 blockaddr, const uint32 prog_addr, const uint16 data)
{
	volatile uint16 *ba = (volatile uint16 *)blockaddr;
	
	ba[AMD_CMD_ADDR1] = AMD_UNLOCK_BYPASS_PGM_DATA1;
	*(volatile uint16*)prog_addr = data;
}

void AMD_Word_Program_CMD(const uint32 blockaddr, const uint32 prog_addr, const uint16 data)
{
	volatile uint16 *ba = (volatile uint16 *)blockaddr;
	
	ba[AMD_CMD_ADDR1] = AMD_WORD_PGM_DATA1;
	ba[AMD_CMD_ADDR2] = AMD_WORD_PGM_DATA2;
	ba[AMD_CMD_ADDR1] = AMD_WORD_PGM_DATA3;
	*(volatile uint16*)prog_addr = data;
}

STATUS_E AMD_Program_CheckDone_By_Toggle(const uint32 prog_addr)
{
	volatile uint16 stat_data1;
	volatile uint16 stat_data2;
	
	stat_data1 = *(volatile uint16*)prog_addr;
	stat_data2 = *(volatile uint16*)prog_addr;

	if( (stat_data1&AMD_DQ6_TOGGLE_BIT) == (stat_data2&AMD_DQ6_TOGGLE_BIT) )
	{
		return S_DONE;
	}
	
	if( (stat_data1&AMD_DQ5_TIMEOUT_ERR_BIT) )
	{
		stat_data1 = *(volatile uint16*)prog_addr;
		stat_data2 = *(volatile uint16*)prog_addr;
		if( (stat_data1&AMD_DQ6_TOGGLE_BIT) == (stat_data2&AMD_DQ6_TOGGLE_BIT) )
		{
			return S_DONE;
		}
		else
		{
			return S_PGM_FAILED;
		}
	}

	return S_IN_PROGRESS;
}

//------------------------------------------------------------------------------
// MirrorBit Related Callback Function                                          
//------------------------------------------------------------------------------
void AMD_MirrorBit_Erase_CMD(const uint32 blockaddr)
{
	volatile uint32 i;

	AMD_Erase_CMD(blockaddr);

	//final step, wait for 10us 
	for (i=0;i<1000;i++);
}

void AMD_MirrorBit_PreProcess(const uint16 dev)
{
	g_FLASH_MAX_BUFPGM_SIZE_IN_BYTE = 64;
}

void AMD_MirrorBit_Buf_Program_CMD(const uint32 blockaddr, const uint32 prog_addr, const uint16 *data, const uint32 length_in_word)
{
	volatile uint32 i;
	volatile uint16 *ba = (volatile uint16 *)blockaddr;
	volatile uint16 *prog_word_addr = (volatile uint16*)prog_addr;
	volatile uint16 *data_word_addr = (volatile uint16*)data;

	ba[AMD_CMD_ADDR1] = AMD_BUF_PGM_DATA1;
	ba[AMD_CMD_ADDR2] = AMD_BUF_PGM_DATA2;
	ba[0] = AMD_BUF_PGM_DATA3;
	ba[0] = (uint16)(length_in_word - 1); 

	for(i=0;i<length_in_word;i++)
	{
		*prog_word_addr++ = *data_word_addr++;
	}

	ba[0] = AMD_BUF_PGM_LAST;

	//final step, wait for 10us 
	for (i=0;i<1000;i++);
}

//------------------------------------------------------------------------------
// Protection Related Callback Function                                         
//------------------------------------------------------------------------------
#ifdef AMD_PROTECTION_ENABLED
void AMD_UnprotectChip(const uint16 dev) {
	uint32	die;
	uint32	die_baseaddr;
	uint32	addr;
	uint32	die_size;
	uint32	blk_size;

	// charge all PPBs to 1 
	for(die=0; die<FLASH_DIE_COUNT(dev); die++) {
		die_size = FLASH_DIE_SIZE(dev, die);
		addr = die_baseaddr = FUTL_GetFlashDieBaseAddr(die);
		while( addr < (die_baseaddr+die_size) ) {
			// set PPB to 1 
			if(!AMD_Protection_PPB_Program_CMD(addr)) {
				while(1);
			}
			// current sector size 
			FUTL_SearchBaseAddr(addr, NULL, &blk_size);
			// next sector address 
			addr += blk_size;
		}
	}

	// issue erase all PPBs command 
	if(!AMD_Protection_Erase_All_PPBs_CMD(FUTL_GetFlashDieBaseAddr(0))) {
		while(1);
	}
}

bool AMD_Protection_PPB_Program_CMD(uint32 blockaddr)
{
	volatile uint16 *ba = (volatile uint16 *)blockaddr;
	volatile bool ok_flag = FALSE;
	volatile uint32	i;
	
	ba[AMD_CMD_ADDR1] = AMD_PROTECT_PPB_PGM_DATA1;
	ba[AMD_CMD_ADDR2] = AMD_PROTECT_PPB_PGM_DATA2;
	ba[AMD_CMD_ADDR1] = AMD_PROTECT_PPB_PGM_DATA3;
	ba[AMD_PROTECT_WP_ADDR] = AMD_PROTECT_PPB_PGM_DATA4;
	// delay 100us 
	for(i=0; i<10000; i++);
	ba[AMD_PROTECT_WP_ADDR] = AMD_PROTECT_PPB_PGM_DATA5;
	if(!(ba[AMD_PROTECT_WP_ADDR]&AMD_PROTECT_PPB_SET)) {
		ok_flag = FALSE;
	}
	else {
		ok_flag = TRUE;
	}

	// enter auto-select mode 
	ba[AMD_CMD_ADDR1] = AMD_ENTER_AUTOSELECT_MODE_DATA1;
	ba[AMD_CMD_ADDR2] = AMD_ENTER_AUTOSELECT_MODE_DATA2;
	ba[AMD_CMD_ADDR1] = AMD_ENTER_AUTOSELECT_MODE_DATA3;

	// reset to read mode 
	ba[AMD_SA_ADDR] = AMD_RESET_TO_READ_MODE_DATA1;

	return ok_flag;
}

bool AMD_Protection_PPB_Status_CMD(uint32 blockaddr)
{
	volatile uint16 *ba = (volatile uint16 *)blockaddr;
	volatile bool ok_flag = FALSE;
	
	ba[AMD_CMD_ADDR1] = AMD_PROTECT_PPB_STATUS_DATA1;
	ba[AMD_CMD_ADDR2] = AMD_PROTECT_PPB_STATUS_DATA2;
	ba[AMD_CMD_ADDR1] = AMD_PROTECT_PPB_STATUS_DATA3;
	ba[AMD_PROTECT_WP_ADDR] = AMD_PROTECT_PPB_STATUS_DATA4;
	if(!(ba[AMD_PROTECT_WP_ADDR]&AMD_PROTECT_PPB_SET)) {
		ok_flag = FALSE;
	}
	else {
		ok_flag = TRUE;
	}

	// reset to read mode 
	ba[AMD_SA_ADDR] = AMD_RESET_TO_READ_MODE_DATA1;

	return ok_flag;
}

bool AMD_Protection_Erase_All_PPBs_CMD(uint32 blockaddr)
{
	volatile uint16 *ba = (volatile uint16 *)blockaddr;
	volatile uint32	i;
	volatile bool ok_flag=FALSE;
	
	ba[AMD_CMD_ADDR1] = AMD_PROTECT_PPB_ERASE_DATA1;
	ba[AMD_CMD_ADDR2] = AMD_PROTECT_PPB_ERASE_DATA2;
	ba[AMD_CMD_ADDR1] = AMD_PROTECT_PPB_ERASE_DATA3;
	ba[AMD_PROTECT_WP_ADDR] = AMD_PROTECT_PPB_ERASE_DATA4;
	// delay 1.2ms 
	for(i=0; i<0x30000; i++);
	ba[AMD_SA_ADDR] = AMD_PROTECT_PPB_ERASE_DATA5;
	if(ba[AMD_PROTECT_WP_ADDR]&AMD_PROTECT_PPB_SET) {
		ok_flag = TRUE;
	}
	else {
		ok_flag = FALSE;
	}
	
	// reset to read mode 
	ba[AMD_SA_ADDR] = AMD_RESET_TO_READ_MODE_DATA1;
	
	return ok_flag;
}
#endif

⌨️ 快捷键说明

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