📄 amd.c
字号:
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_4_ADDR_EXIT_SECSI, CYCLE_4_DATA_EXIT_SECSI);
// Get driver prog info & store for easy access.
// Single datum timeouts
if (pFlashDesc->SysInt.Typical.SnglWordProgTO_us)
g_FlashProgInfo.ulDatumProgTO_us = (1 << pFlashDesc->SysInt.Typical.SnglWordProgTO_us);
else
g_FlashProgInfo.ulDatumProgTO_us = POLLING_WRBYPASS_LIFETIME_US;
if (pFlashDesc->SysInt.Max.SnglWordProgTO_us)
g_FlashProgInfo.ulMaxDatumProgTOFactor = 1 << pFlashDesc->SysInt.Max.SnglWordProgTO_us;
else
g_FlashProgInfo.ulMaxDatumProgTOFactor = POLLING_WRBYPASS_LIFETIME_FACTOR;
// Write buffer timeouts.
if (pFlashDesc->SysInt.Typical.WriteBuffTO_us)
g_FlashProgInfo.ulBufferProgTO_us = (1 << (pFlashDesc->SysInt.Typical.WriteBuffTO_us));
else
g_FlashProgInfo.ulBufferProgTO_us = POLLING_WRBUFR_LIFETIME_US;
if (pFlashDesc->SysInt.Max.WriteBuffTO_us)
g_FlashProgInfo.ulMaxBufferProgTOFactor = 1 << pFlashDesc->SysInt.Max.WriteBuffTO_us;
else
g_FlashProgInfo.ulMaxBufferProgTOFactor = POLLING_WRBUFR_LIFETIME_FACTOR;
// Sector erase timeouts
if (pFlashDesc->SysInt.Typical.BlockEraseTO_ms)
g_FlashProgInfo.ulSectorEraseTO_ms = (1 << pFlashDesc->SysInt.Typical.BlockEraseTO_ms);
else
g_FlashProgInfo.ulSectorEraseTO_ms = ERASE_BLOCK_TIMEOUT_MS;
if (pFlashDesc->SysInt.Max.BlockEraseTO_ms)
g_FlashProgInfo.ulMaxSectorEraseTOFactor = 1 << pFlashDesc->SysInt.Max.BlockEraseTO_ms;
else
g_FlashProgInfo.ulMaxSectorEraseTOFactor = ERASE_BLOCK_TIMEOUT_FACTOR;
// Chip erase timeouts
if (pFlashDesc->SysInt.Typical.ChipEraseTO_ms)
g_FlashProgInfo.ulChipEraseTO_ms = (1 << pFlashDesc->SysInt.Typical.ChipEraseTO_ms);
else
g_FlashProgInfo.ulChipEraseTO_ms = ERASE_CHIP_TIMEOUT_MS;
if (pFlashDesc->SysInt.Max.ChipEraseTO_ms)
g_FlashProgInfo.ulMaxChipEraseTOFactor = 1 << pFlashDesc->SysInt.Max.ChipEraseTO_ms;
else
g_FlashProgInfo.ulMaxChipEraseTOFactor = ERASE_CHIP_TIMEOUT_FACTOR;
PrintFlashProgInfo(&g_FlashProgInfo);
// Set device width
pFlashDesc->DeviceWidth = 16;
pFlashDesc->PairedFlash = bIsPaired;
#ifdef USE_OS_SERVICES
// Calibrate CEDDK's counter for the StallExecution() API
CalibrateStallCounter();
#endif
_exit:
// exit CFI query mode by issuing a soft reset
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_RESET, CYCLE_1_DATA_RESET);
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("AMD_IsFlashSupported-\r\n")));
return bSuccess;
}
//-----------------------------------------------------------------------------
//
// Function: AMDx16_Program
//
// Function performs programming of AMD 16bit mode flash devices.
//
// Programming Notes:
// DQ7 indicates the programming is complete however this does not
// guarantee the value that was programmed to the device is correct
// Test to make sure the data programmed is the data that is being
// read from the device.
// ****************************************************************
// Note:
// Just prior to the completion of an Embedded Program or Erase
// operation, DQ7 may change asynchronously with DQ0朌Q6 while
// Output Enable (OE#) is asserted low. That is, the device may
// change from providing status information to valid data on DQ7.
// Depending on when the system samples the DQ7 output, it may read
// the status or valid data. Even if the device has completed
// the program or erase operation and DQ7 has valid data, the data
// outputs on DQ0朌Q6 may be still invalid. Valid data on DQ0朌Q7
// will appear on successive read cycles.
// ****************************************************************
// If DQ5 is a 1, it may not necessarily be true that a time out has
// occurred and the value should be checked once more to see if it
// was successfully programmed.
// In addition the value that was programmed may have this bit set
// in which case the check for the proper value is also required.
// *****************************************************************
//
// Parameters:
// pFlashDesc
// [in] pointer to NOR flash descriptor
//
// ulStartAddress
// [in] start address to start programming
//
// pData
// [in] ptr to data buffer
//
// ulLen
// [in] length of data
//
// Returns:
// FALSE if programming failed
//
//-----------------------------------------------------------------------------
BOOL AMDx16_Program(NOR_FLASH_DESC *pFlashDesc, ULONG ulProgramAddress,
UCHAR *pData, ULONG ulLen, BOOL bIgnore0to1)
{
ULONG ulFlashBase;
BOOL bIsPaired;
ULONG *pulData;
ULONG i;
ULONG j;
ULONG retry;
DWORD dwBusWidth;
ULONG ulWriteBufferSize;
ULONG ulBufAlignBytes;
ULONG ulBufAlignTailBytes;
ULONG dwNumPages;
ULONG ulProgBytes;
ULONG ulDataToWrite;
ULONG ulDataWritten;
ULONG ulDataRead;
ULONG ulBufDatumSize;
ULONG ulFlashSectorAddr;
ULONG ulSectorSize;
ULONG ulCurRegion;
ULONG ulCurBlock;
ULONG ulNumRegionBlocks;
BOOL bDone;
BOOL bSuccess;
ULONG ulIgnoreBuffer[AMD_BUF_PROG_MAX_DATUM];
#ifdef DEBUG
ULONG ulPageStart;
#endif
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("AMDx16_Program+: 0x%x 0x%x 0x%x\r\n"),
ulProgramAddress, pData, ulLen));
if (!pFlashDesc && !pData) {
DEBUGMSG(ZONE_HAL_ERROR, (TEXT("AMDx16_Program: null param\r\n")));
return FALSE;
}
bIsPaired = pFlashDesc->PairedFlash;
ulFlashBase = pFlashDesc->FlashBase;
// Let the flash know the size of the buffer we plan to send
// Note: that this is a 0-based word count and we simulatenously
// write it to both flash parts (upper and lower).
ulWriteBufferSize = (pFlashDesc->Geometry.WriteBuffSize) ?
(bIsPaired ? ((1 << pFlashDesc->Geometry.WriteBuffSize) * 2) :
(1 << pFlashDesc->Geometry.WriteBuffSize)) : 0;
dwNumPages = (ulWriteBufferSize) ? (ulLen / ulWriteBufferSize) : 0;
ulBufAlignBytes = (ulWriteBufferSize) ? ulProgramAddress % ulWriteBufferSize : 0;
ulBufAlignTailBytes = (ulWriteBufferSize) ? ((ulLen - ulBufAlignBytes) % ulWriteBufferSize) : 0;
pulData = (ULONG *)pData;
bSuccess = TRUE;
DEBUGMSG(ZONE_HAL_INFO, (TEXT("ulWriteBufferSize 0x%x\r\n"), ulWriteBufferSize));
// Use bypass mode single datum non-buffered program method for
// 1. no write buffer support or data < 1 page.
// 2. Align program address to write buffer page
// Refer to single word program operation in flash specification
// for more details
dwBusWidth = bIsPaired? sizeof(ULONG) : sizeof(USHORT);
if ((ulBufAlignBytes != 0) || (dwNumPages == 0)) {
ulProgBytes = (ulWriteBufferSize) ? ulBufAlignBytes : ulLen;
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("dwBufAlignBytes 0x%x dwNumPages 0x%x ulProgBytes 0x%x\r\n"),
ulBufAlignBytes, dwNumPages, ulProgBytes));
for (i = 0; i < ulProgBytes; i += dwBusWidth) {
bDone = FALSE;
ulDataToWrite = bIsPaired ? *(ULONG *)pulData : *(USHORT *)pulData;
if (bIgnore0to1) {
ulDataWritten = bIsPaired ? *(volatile ULONG *)ulProgramAddress :
*(volatile USHORT *)ulProgramAddress;
ulDataToWrite &= ulDataWritten;
}
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("Before: [0x%x] 0x%x\r\n"),
ulProgramAddress, bIsPaired ? *((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress))));
if (g_FlashProgInfo.bUnlockBypassSupport) {
// Send unlock bypass enter command for first datum
if (i == 0) {
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_1_ADDR_UNLOCK_x16, CYCLE_1_DATA_UNLOCK);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_2_ADDR_UNLOCK_x16, CYCLE_2_DATA_UNLOCK);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_3_ADDR_CMD_x16, CYCLE_3_DATA_UNLOCK_BYPASS);
}
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_1_ADDR_PROGRAM_BYPASS, CYCLE_1_DATA_PROGRAM_BYPASS);
WR_FLASH_16(bIsPaired, ulProgramAddress, ulDataToWrite);
} else {
// 4 cycle per datum program
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_1_ADDR_UNLOCK_x16, CYCLE_1_DATA_UNLOCK);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_2_ADDR_UNLOCK_x16, CYCLE_2_DATA_UNLOCK);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
UNLOCK_ADDR1_x16, CYCLE_3_DATA_PROGRAM);
WR_FLASH_16(bIsPaired, ulProgramAddress, ulDataToWrite);
}
j = 0;
while (!bDone && bSuccess && (j++ < CHECK_STATUS_TIMEOUT)) {
// Read 1
ulDataWritten = bIsPaired ?
*((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
// D7 will be driven to complement of D7 written to the FLASH.
// When it is driven to the value just written,
// the program operation is complete.
if ((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16)) ==
(ulDataToWrite & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16))) {
// DQ7 = valid data, do Read2 and Read 3
ulDataWritten = bIsPaired ?
*((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
ulDataWritten = bIsPaired ?
*((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
// Spec indiates that D7 may be valid while other data lines are still invalid.
if (ulDataWritten != ulDataToWrite) {
// Try reading again before we report an error. We want to avoid
// reporting an error here because EBOOT has no recovery and
// will terminate the flashing procedure.
for (retry = 10; retry > 0 && !bDone; retry--) {
ulDataWritten = bIsPaired ?
*((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
if (ulDataWritten == ulDataToWrite) {
// Programmed properly
bDone = TRUE;
}
}
// Now report an error if the value we wanted did not get programmed
if (!bDone) {
// Programming failure
ERRORMSG(ZONE_HAL_ERROR,
(TEXT("Program failure [0x%x] 0x%x : expect 0x%x\r\n"),
ulProgramAddress, ulDataWritten, ulDataToWrite));
bSuccess = FALSE;
}
} else {
// Datum is programmed properly
bDone = TRUE;
}
} else {
if ((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ5_X16)) ==
CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ5_X16)) {
// Read 2
ulDataWritten = bIsPaired ?
*((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
// Read 3
ulDataRead = bIsPaired ?
*((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -