📄 flash_mtd.amd.c
字号:
{
data_test1 = *(volatile kal_uint16*)addr;
data_test2 = *(volatile kal_uint16*)addr;
if((data_test1 ^ data_test2) & TOGGLE_BUSY)
{
status = OTP_ERR_WAIT;
}
}
else
{
status = OTP_ERR_BUSY;
}
INT_RestoreDataCache(data_cache_id);
return status;
}
/*************************************************************************
* FUNCTION
* OTPRead
*
* DESCRIPTION
* This function implements the OTP read function, first it enter
* secured silicon sector, and read data from "Offset", totally read
* "Length" bytes, then exit secured silicon sector mode
*
* PARAMETERS
* D: driver structure
* Offset: the start position want to read (unit:bytes)
* BufferPtr: the buffer address want to read to
* Length: total length want to read (unit: bytes)
*
* RETURNS
* FS_NO_ERROR: no error
* FS_FLASH_OTP_OVERSCOPE: reading range is out of OTP range
*
*************************************************************************/
/* While the Secured Silicon Sector access is enabled, simultaneous
* operations are not allow fro bank A.
*/
kal_int32
OTPRead_AMD(void * DriveData,
kal_uint32 Offset,
void * BufferPtr,
kal_uint32 Length)
{
NOR_Flash_MTD_Data * MTDData = DriveData;
kal_uint32 savedMask,i;
volatile FLASH_CELL *BaseAddr;
kal_uint8 *src,*dest;
kal_uint32 data_cache_id;
/* drvier initialization test */
ASSERT((~MTDData->Signature == (kal_uint32)MTDData->RegionInfo));
BaseAddr = (volatile FLASH_CELL *)INT_RetrieveFlashBaseAddr();
src = (kal_uint8 *)((kal_uint32)BaseAddr + NOR_OTPOffset + Offset);
dest =(kal_uint8 *)BufferPtr;
/* Base Addr check */
ASSERT(!(((kal_uint32)BaseAddr) % sizeof(FLASH_CELL)));
/* check if read scope is out of range */
if( (Offset > NOR_OTPLength) ||
(Offset+ Length)> NOR_OTPLength )
{
return FS_FLASH_OTP_OVERSCOPE;
}
/* Disable Interrupt */
savedMask = SaveAndSetIRQMask();
data_cache_id = INT_DisableDataCache();
/* Enter Secured Silicon Sector Mode */
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_OTP_ENTRY;
/* Read Secured Silicon Sector Data */
for(i=0; i< Length; i++)
dest[i] = src[i];
/* Exit Secured Silicon Sector Mode */
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_OTP_EXIT;
BaseAddr[0] = CMD_OTP_ZERO;
/* Enable Interrupt */
INT_RestoreDataCache(data_cache_id);
RestoreIRQMask(savedMask);
return FS_NO_ERROR;
}
/*************************************************************************
* FUNCTION
* OTPWrite
*
* DESCRIPTION
* This function implements the OTP write function, first it enter
* secured silicon sector, and write data from "Offset", totally write
* "Length" bytes, then exit secured silicon sector mode.
* Be carefully, do not set bit to one if it is zero
*
* PARAMETERS
* D: driver structure
* Offset: the start position want to write (unit:bytes)
* BufferPtr: the buffer address want to write from
* Length: total length want to write (unit: bytes)
*
* RETURNS
* FS_NO_ERROR: no error
* FS_FLASH_OTP_OVERSCOPE: writing range is out of OTP range
* FS_FLASH_OTP_LOCK_ALREADY: OTP area is already locked
*
*************************************************************************/
kal_int32
OTPWrite_AMD(void * DriveData,
kal_uint32 Offset,
void * BufferPtr,
kal_uint32 Length)
{
NOR_Flash_MTD_Data * MTDData = DriveData;
kal_uint32 savedMask,DoneLength=0;
volatile FLASH_CELL *BaseAddr;
FLASH_CELL IndicatorBit;
kal_int32 status;
kal_uint8 *src,*dest;
kal_uint16 *dest16;
FLASH_CELL CELL;
kal_uint8 *CELLPtr = (kal_uint8 *)&CELL;
/* drvier initialization test */
ASSERT((~MTDData->Signature == (kal_uint32)MTDData->RegionInfo));
BaseAddr = (volatile FLASH_CELL*)INT_RetrieveFlashBaseAddr();
dest = (kal_uint8 *)((kal_uint32)BaseAddr + NOR_OTPOffset + Offset);
src =(kal_uint8 *)BufferPtr;
/* Base Addr check */
ASSERT(!(((kal_uint32)BaseAddr) % sizeof(FLASH_CELL)));
/* check if read scope is out of range */
if( (Offset > NOR_OTPLength) ||
(Offset+ Length)> NOR_OTPLength )
{
return FS_FLASH_OTP_OVERSCOPE;
}
/* Disable Interrupt */
savedMask = SaveAndSetIRQMask();
/* Enter Auto Select Mode */
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_AUTOSELECT_ENTRY;
IndicatorBit = BaseAddr[3];
/* Exit Auto Select Mode */
BaseAddr[0] = CMD_AUTOSELECT_EXIT;
/* Enable Interrupt */
RestoreIRQMask(savedMask);
if ((IndicatorBit & 0x40))
{
return FS_FLASH_OTP_LOCK_ALREADY;
}
while ( DoneLength < Length )
{
/* Disable Interrupt */
savedMask = SaveAndSetIRQMask();
/* Enter Secured Silicon Sector Mode */
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_OTP_ENTRY;
//enter write command to flash
if ( ((kal_uint32)dest&(sizeof(FLASH_CELL)-1)) || ((Length-DoneLength)==1) ) //not word align
{
kal_uint32 ofs = ((kal_uint32) dest) & (sizeof(FLASH_CELL)-1);
kal_uint8 *b = (kal_uint8 *)&CELL;
dest16 = (kal_uint16 *)(((kal_uint32)dest) & ~(sizeof(FLASH_CELL)-1));
CELL = dest16[0];
b[ofs] = src[0];
}
else //word align
{
dest16 = (kal_uint16 *)dest;
CELLPtr[0] = src[0];
CELLPtr[1] = src[1];
}
/*check write content:attempt to set bits in flash (0->1) */
if((~(dest16[0])) & CELL)
{
/* exit secured Silicon Sector Mode */
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_OTP_EXIT;
BaseAddr[0] = CMD_OTP_ZERO;
/* Enable Interrupt */
RestoreIRQMask(savedMask);
ASSERT(0);
}
//write one word to flash
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_PROG;
dest16[0] = CELL;
/* check till ready */
while(1)
{
status = OTPCheckWriteReady_AMD((kal_uint32)dest16 ,(kal_uint16) CELL);
if(status == OTP_ERR_NONE)
{
break;
}else if(status == OTP_ERR_WAIT)
{
/* exit secured Silicon Sector Mode */
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_OTP_EXIT;
BaseAddr[0] = CMD_OTP_ZERO;
/* Enable Interrupt */
RestoreIRQMask(savedMask);
ASSERT(0);
}
}
/* Exit Secured Silicon Sector Mode */
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_OTP_EXIT;
BaseAddr[0] = CMD_OTP_ZERO;
/* Enable Interrupt */
RestoreIRQMask(savedMask);
/* addr offset */
if ( ((kal_uint32)dest&(sizeof(FLASH_CELL)-1)) || ((Length-DoneLength)==1) ) //not word align
{
dest+=1;
src+=1;
DoneLength+=1;
}
else
{
dest+=2;
src+=2;
DoneLength+=2;
}
}
return FS_NO_ERROR;
}
/*************************************************************************
* FUNCTION
* OTPLock
*
* DESCRIPTION
* This function implements the OTP lock function.
* PARAMETERS
* D: driver structure
*
* RETURNS
* FS_NO_ERROR: no error
* FS_FLASH_OTP_LOCK_ALREADY: OTP area is already locked
*
*************************************************************************/
kal_int32
OTPLock_AMD(void * DriveData)
{
NOR_Flash_MTD_Data * MTDData = DriveData;
kal_uint32 savedMask;
volatile FLASH_CELL *BaseAddr = (volatile FLASH_CELL*)INT_RetrieveFlashBaseAddr();
FLASH_CELL IndicatorBit,CELL;
kal_int32 status;
/* drvier initialization test */
ASSERT((~MTDData->Signature == (kal_uint32)MTDData->RegionInfo));
/* Disable Interrupt */
savedMask = SaveAndSetIRQMask();
/* Enter Auto Select Mode */
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_AUTOSELECT_ENTRY;
IndicatorBit = BaseAddr[3];
/* Exit Auto Select Mode */
BaseAddr[0] = CMD_AUTOSELECT_EXIT;
if ((IndicatorBit & 0x40))
{
/* Enable Interrupt */
RestoreIRQMask(savedMask);
return FS_FLASH_OTP_LOCK_ALREADY;
}
/* Enter Lock Register Mode */
BaseAddr[ADDR_UNLOCK_1] = CMD_UNLOCK_1;
BaseAddr[ADDR_UNLOCK_2] = CMD_UNLOCK_2;
BaseAddr[ADDR_UNLOCK_1] = CMD_LOCKREG_ENTRY;
CELL = BaseAddr[0];
CELL &= 0xFFFE;
BaseAddr[0] = CMD_LOCKREG_PROG;
BaseAddr[0] = CELL;
DelayAWhile_AMD();
/* check till ready */
while( (status = OTPCheckWriteReady_AMD((kal_uint32)BaseAddr ,(kal_uint16) CELL)) != OTP_ERR_NONE)
{
if (status == OTP_ERR_WAIT)
{
BaseAddr[0] = CMD_RESET;
/* Enable Interrupt */
RestoreIRQMask(savedMask);
ASSERT(0);
}
}
BaseAddr[0] = CMD_LOCKREG_EXIT1;
BaseAddr[0] = CMD_LOCKREG_EXIT2;
/* Enable Interrupt */
RestoreIRQMask(savedMask);
return FS_NO_ERROR;
}
kal_int32
OTPAccess_AMD(void * DriveData, kal_int32 accesstype, kal_uint32 Offset, void * BufferPtr, kal_uint32 Length)
{
if (accesstype==FS_OTP_READ)
{
return OTPRead_AMD(DriveData, Offset, BufferPtr,Length);
}
else if (accesstype==FS_OTP_WRITE)
{
return OTPWrite_AMD(DriveData,Offset,BufferPtr,Length);
}
else if (accesstype==FS_OTP_LOCK)
{
return OTPLock_AMD(DriveData);
}
else
{
ASSERT(0);
}
}
kal_int32
OTPQueryLength_AMD(void * DriveData, UINT *LengthPtr)
{
*LengthPtr = NOR_OTPLength;
return FS_NO_ERROR;
}
#ifdef __MTK_TARGET__
#pragma arm section code
#endif /* __MTK_TARGET__ */
# endif /*__SECURITY_OTP__*/
/*-----------------------------------*/
NOR_MTD_Driver DriverName =
{
MountDevice_AMD,
ShutDown_AMD,
MapWindow,
EraseBlock_AMD,
#if (defined(__TOSHIBA_TV__) || defined(__TOSHIBA_TY__))
ProgramData_TOSHIBA,
#else
ProgramData_AMD,
#endif
NonBlockEraseBlock_AMD,
CheckDeviceReady_AMD,
SuspendErase_AMD,
ResumeErase_AMD,
NULL,
#ifdef __SECURITY_OTP__
OTPAccess_AMD,
OTPQueryLength_AMD
#else
NULL,
NULL
#endif
};
#endif //__AMD_SERIES_NOR__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -