flash_mtd.amd.c
来自「8032底层驱动部分。因为可以移植 所以单独来拿出来」· C语言 代码 · 共 1,645 行 · 第 1/4 页
C
1,645 行
fp[i] = Cell;
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
WaitReady_AMD((kal_uint32)&fp[i], (kal_uint16)Cell);
RestoreIRQMask(savedMask);
#else
RestoreIRQMask(savedMask);
WaitReady_AMD((kal_uint32)&fp[i], (kal_uint16)Cell);
#endif
}
#else
j = 0;
Words = (Length/sizeof(FLASH_CELL));
while(Words>0)
{
ProgramWords = Words > PAGE_BUFFER_SIZE ? PAGE_BUFFER_SIZE : Words ;
if ((kal_uint32)fp & (sizeof(FLASH_CELL)*PAGE_BUFFER_SIZE -1))
{
FLASH_CELL *pageb = (FLASH_CELL *)((kal_uint32)(fp+ PAGE_BUFFER_SIZE) & (~(sizeof(FLASH_CELL)*PAGE_BUFFER_SIZE -1)));
if ( ProgramWords > (pageb-fp))
ProgramWords = pageb - fp;
}
savedMask = SaveAndSetIRQMask();
bp[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
bp[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
fp[0] = CMD_WRITETOBUFFER;
fp[0] = ProgramWords -1;// set data count
for(i = 0; i < ProgramWords; i++)
{
b[0] = bdp[j++];
b[1] = bdp[j++];
fp[i] = Cell;
}
fp[0] = CMD_BUFFERTOFLASH;
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
WaitReady_AMD((kal_uint32)&fp[ProgramWords -1], (kal_uint16)Cell);
RestoreIRQMask(savedMask);
#else
RestoreIRQMask(savedMask);
#ifdef __SPANSION_PL_N__
DelayAWhile_AMD();
#endif //__SPANSION_PL_N__
WaitReady_AMD((kal_uint32)&fp[ProgramWords -1], (kal_uint16)Cell);
#endif
Words -= ProgramWords;
fp += ProgramWords;
}
#endif
}
else
{
FLASH_CELL *dp = (FLASH_CELL*)Data;
#ifndef __PAGE_BUFFER_PROGRAM__
for(i = 0; i < Length/sizeof(FLASH_CELL); i++)
{
savedMask = SaveAndSetIRQMask();
bp[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
bp[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
bp[ADDR_UNLOCK_1] = CMD_PROG;
fp[i] = dp[i];
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
WaitReady_AMD((kal_uint32)&fp[i], (kal_uint16)dp[i]);
RestoreIRQMask(savedMask);
#else
RestoreIRQMask(savedMask);
WaitReady_AMD((kal_uint32)&fp[i], (kal_uint16)dp[i]);
#endif
}
#else
Words = (Length/sizeof(FLASH_CELL));
while(Words>0)
{
ProgramWords = Words > PAGE_BUFFER_SIZE ? PAGE_BUFFER_SIZE : Words ;
if ((kal_uint32)fp & (sizeof(FLASH_CELL)*PAGE_BUFFER_SIZE -1))
{
FLASH_CELL *pageb = (FLASH_CELL *)((kal_uint32)(fp+ PAGE_BUFFER_SIZE) & (~(sizeof(FLASH_CELL)*PAGE_BUFFER_SIZE -1)));
if ( ProgramWords > (pageb-fp))
ProgramWords = pageb - fp;
}
savedMask = SaveAndSetIRQMask();
bp[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
bp[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
fp[0] = CMD_WRITETOBUFFER;
fp[0] = ProgramWords -1;// set data count
for(i = 0; i < ProgramWords; i++)
{
fp[i] = dp[i];
}
fp[0] = CMD_BUFFERTOFLASH;
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
WaitReady_AMD((kal_uint32)&fp[ProgramWords -1], (kal_uint16)dp[ProgramWords -1]);
RestoreIRQMask(savedMask);
#else //_LOW_COST_SINGLE_BANK_FLASH_
RestoreIRQMask(savedMask);
#ifdef __SPANSION_PL_N__
DelayAWhile_AMD();
#endif //__SPANSION_PL_N__
WaitReady_AMD((kal_uint32)&fp[ProgramWords -1], (kal_uint16)dp[ProgramWords -1]);
#endif //_LOW_COST_SINGLE_BANK_FLASH_
Words -= ProgramWords;
fp += ProgramWords;
dp += ProgramWords;
}
#endif
}
}
break;
}
return FS_NO_ERROR;
}
#endif //__TOSHIBA_TV__
/*-----------------------------------*/
static int NonBlockEraseBlock_AMD(void * DriveData, kal_uint32 BlockIndex) /* Added by Eric */
{
#ifndef __NOR_FDM5__
NOR_Flash_MTD_Data * D = DriveData;
volatile FLASH_CELL * fp = (volatile FLASH_CELL *) D->CurrAddr;
#ifdef DEBUG
//EraseBlock: block not mapped
ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
#endif
ASSERT((~D->Signature == (kal_uint32)D->RegionInfo));
#else
NOR_MTD_DATA *D= DriveData;
volatile FLASH_CELL * fp = (volatile FLASH_CELL *)BlockAddress(D,BlockIndex);
ASSERT(D->Signature == ~((kal_uint32)D->LayoutInfo));
#endif
EraseCommand_AMD(fp);
#ifdef __SPANSION_PL_N__
DelayAWhile_AMD();
#endif
return FS_NO_ERROR;
}
/*-----------------------------------*/
static int CheckDeviceReady_AMD(void * DriveData, kal_uint32 BlockIndex) /* Added by Eric */
{
FLASH_CELL s1, s2;
kal_uint32 data_cache_id;
#ifndef __PRODUCTION_RELEASE__
static kal_uint32 test_times=0;
#endif
#ifndef __NOR_FDM5__
NOR_Flash_MTD_Data * D = DriveData;
volatile FLASH_CELL * fp = (volatile FLASH_CELL *) D->CurrAddr;
#ifdef DEBUG
//EraseBlock: block not mapped
ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
#endif
ASSERT((~D->Signature == (kal_uint32)D->RegionInfo));
#else
NOR_MTD_DATA *D= DriveData;
volatile FLASH_CELL * fp = (volatile FLASH_CELL *)BlockAddress(D,BlockIndex);
ASSERT(D->Signature == ~((kal_uint32)D->LayoutInfo));
#endif
data_cache_id = INT_DisableDataCache();
s1 = fp[1];
s2 = fp[1];
if (((s1 ^ s2) & TOGGLE_ERASE_SUSPEND))
{
if(!((s1 ^ s2) & TOGGLE_BUSY))
{
/* flash is erase suspended */
fp[0] = CMD_RESU_SEC_ERASE;
}
INT_RestoreDataCache(data_cache_id);
return FS_FLASH_ERASE_BUSY;
}
else
{
s1 = fp[1];
s2 = fp[1];
if(s2 == 0xffff)
{
INT_RestoreDataCache(data_cache_id);
#ifndef __PRODUCTION_RELEASE__
test_times = 0;
#endif
return FS_NO_ERROR;
}
else
{
/* the erase operation is reset abnormally */
if(!(s1 ^ s2))
{
#ifndef __PRODUCTION_RELEASE__
/* MAUI_00218339: S71PL129JB0BAW9U need another busy time before */
/* polling, modify to allow second erase command to solve this issue */
test_times++;
if (test_times > 1)
ASSERT(0);
#endif
EraseCommand_AMD(fp);
}
INT_RestoreDataCache(data_cache_id);
return FS_FLASH_ERASE_BUSY;
}
}
}
/*-----------------------------------*/
static int SuspendErase_AMD(void * DriveData, kal_uint32 BlockIndex) /* Added by Eric */
{
FLASH_CELL s;
kal_uint32 data_cache_id;
#ifndef __NOR_FDM5__
NOR_Flash_MTD_Data * D = DriveData;
volatile FLASH_CELL * fp = (volatile FLASH_CELL *) D->CurrAddr;
#ifdef DEBUG
//EraseBlock: block not mapped
ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
#endif
#else
NOR_MTD_DATA *D= DriveData;
volatile FLASH_CELL * fp = (volatile FLASH_CELL *)BlockAddress(D,BlockIndex);
#endif
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
kal_uint32 savedMask;
savedMask = SaveAndSetIRQMask();
#endif
data_cache_id = INT_DisableDataCache();
#ifdef DEBUG
#ifndef _LOW_COST_SINGLE_BANK_FLASH_
//SuspendErase: block not mapped
ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
#endif
#endif
fp[0] = CMD_SUSP_SEC_ERASE;
s = fp[0];
while(!(s&POLL_BUSY))
s = fp[0];
INT_RestoreDataCache(data_cache_id);
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
RestoreIRQMask(savedMask);
#endif
return FS_NO_ERROR;
}
/*-----------------------------------*/
static int ResumeErase_AMD(void * DriveData, kal_uint32 BlockIndex) /* Added by Eric */
{
#ifndef __NOR_FDM5__
NOR_Flash_MTD_Data * D = DriveData;
volatile FLASH_CELL * fp = (volatile FLASH_CELL *) D->CurrAddr;
#ifdef DEBUG
//EraseBlock: block not mapped
ASSERT(D->CurrAddr == BlockAddress(D, BlockIndex));
#endif
#else
NOR_MTD_DATA *D= DriveData;
volatile FLASH_CELL * fp = (volatile FLASH_CELL *)BlockAddress(D,BlockIndex);
#endif
fp[0] = CMD_RESU_SEC_ERASE;
return FS_NO_ERROR;
}
/********************************************/
/* */
/* FDM5.0 MTD SUPPORT */
/* */
/********************************************/
#ifdef __NOR_FDM5__
static int MountDevice_AMD(void * DriveData, void * Info)
{
NOR_MTD_DATA * D = DriveData;
NORLayoutInfo * Layout = D->LayoutInfo;
kal_uint32 TotalPhysicalPages;
kal_uint32 TblEntryShift=0,j=1;
// check and assign D->LayoutInfo
TotalPhysicalPages = (Layout->BlkSize)/(Layout->PageSize)*(Layout->TotalBlks);
while(j<TotalPhysicalPages)
{
j = j << 1;
TblEntryShift++;
}
TblEntryShift = TblEntryShift>>1;
if((TblEntryShift) >8)
TblEntryShift=8;
Layout->TblEntrys = 1<<TblEntryShift;
if ( (Layout->TblEntrys * Layout->TotalLSMT) < TotalPhysicalPages)
ASSERT(0);
return FS_NO_ERROR;
}
static int ShutDown_AMD(void * DriveData)
{
NOR_MTD_DATA * D = DriveData;
NORBankInfo * BankInfo = D->LayoutInfo->BankInfo;
volatile FLASH_CELL *fp = (volatile FLASH_CELL*)D->BaseAddr;
FLASH_CELL s1, s2;
kal_uint32 i=0,j=0;
for(i=0;BankInfo[i].Banks !=0;i++)
for(j=0;j<BankInfo[i].Banks;j++)
{
while(1)
{
s1 = fp[0];
s2 = fp[0];
if ((s1 ^ s2)==0)
break;
else
{
if(s2 & TOGGLE_TIMEOUT)
{
s1 = fp[0];
s2 = fp[0];
if ((s1 ^ s2)==0)
break;
else
{
fp[0] = CMD_RESET;
break;
}
}
}
}
fp= (volatile FLASH_CELL*)((kal_uint32)fp + (kal_uint32)BankInfo[i].BankSize);
}
return FS_NO_ERROR;
}
#endif
#ifdef _LOW_COST_SINGLE_BANK_FLASH_
#ifdef __MTK_TARGET__
#pragma arm section code
#endif /* __MTK_TARGET__ */
#endif
/****************************************************************************/
/* */
/* Support NOR Flash OTP Function */
/* */
/****************************************************************************/
#ifdef __SECURITY_OTP__
extern kal_uint32 INT_RetrieveFlashBaseAddr(void);
static const kal_uint32 NOR_OTPOffset=0x100;
static const kal_uint32 NOR_OTPLength=0x100;
#define CMD_OTP_ENTRY 0x88
#define CMD_OTP_EXIT 0x90
#define CMD_OTP_ZERO 0x00
#define CMD_AUTOSELECT_ENTRY 0x90
#define CMD_AUTOSELECT_EXIT 0xF0
#define CMD_LOCKREG_ENTRY 0x40
#define CMD_LOCKREG_PROG 0xA0
#define CMD_LOCKREG_EXIT1 0x90
#define CMD_LOCKREG_EXIT2 0x00
#define OTP_ERR_NONE 0
#define OTP_ERR_OVERSCOPE 1
#define OTP_ERR_BUSY 2
#define OTP_ERR_WAIT 3
#ifdef __MTK_TARGET__
#pragma arm section code = "SNORCODE"
#endif /* __MTK_TARGET__ */
kal_int32
OTPCheckWriteReady_AMD(kal_uint32 addr,kal_uint16 data)
{
kal_uint16 data_test1,data_test2;
kal_uint32 data_cache_id;
kal_int32 status = OTP_ERR_NONE;
data_cache_id = INT_DisableDataCache();
data_test1 = *(volatile kal_uint16*)addr;
if((data_test1 & POLL_BUSY) == (data & POLL_BUSY))
{
data_test1 = *(volatile kal_uint16*)addr;
data_test2 = *(volatile kal_uint16*)addr;
if (data_test2 == data)
status = OTP_ERR_NONE;
else
{
status = OTP_ERR_WAIT;
}
}
else if(data_test1 & POLL_TIMEOUT) //DQ5 = 1 may imply a timeout happens
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?