cfi.c
上传用户:fy98168
上传日期:2015-06-26
资源大小:13771k
文件大小:58k
- #include "gendef.h"
- #include "cfi.h"
- #include "osp.h"
- #ifndef SUCCESS
- #define SUCCESS RETOK
- #endif
- #ifndef FAILURE
- #define FAILURE RETFIAL1
- #endif
- #define WORDREG volatile UINT16 *
- #define BYTEREG volatile UINT8 *
- #define CFI_COMMAND_PREAMBLE_1 (0x5555)
- #define CFI_COMMAND_PREAMBLE_2 (0x2AAA)
- #define CFI_COMMAND_TYPE (0x5555)
- #define CFI_COMMAND_PREAMBLE_1_DATA (0xAA)
- #define CFI_COMMAND_PREAMBLE_2_DATA (0x55)
- #define CFI_IDENTIFIER_CODES_ADDRESS (0x5555)
- #define CFI_IDENTIFIER_CODES_COMMAND (0x90)
- #define CFI_MANUF_ID (0x0)
- #define CFI_DEVICE_ID (0x1)
- #define CFI_SECTOR_PROTECT (0x2)
- #define CFI_QUERY_ADDRESS (0x55)
- #define CFI_QUERY_COMMAND (0x98)
- #define CFI_QUERY_Q (0x10)
- #define CFI_QUERY_R (0x11)
- #define CFI_QUERY_Y (0x12)
- #define CFI_VENDOR_COMMAND_SET (0x13)
- #define CFI_EXT_QUERY_TABLE_ADDRESS (0x15)
- #define CFI_ALT_VENDOR_COMMAND_SET (0x17)
- #define CFI_ALT_EXT_QUERY_TABLE_ADDRESS (0x19)
- #define CFI_2N_DEVICE_SIZE (0x27)
- #define CFI_INTERFACE_CODE (0x28)
- #define CFI_2N_MAX_BUFFER_BYTES (0x2A)
- #define CFI_NUM_ERASE_BLOCK_REGIONS (0x2C)
- #define CFI_ERASE_BLOCK_REGION_INFO (0x2D)
- #define CFI_NUM_BLOCKS_IN_REGION_LO (0x0)
- #define CFI_NUM_BLOCKS_IN_REGION_HI (0x1)
- #define CFI_256X_BLOCK_SIZE_LO (0x2)
- #define CFI_256X_BLOCK_SIZE_HI (0x3)
- #define CFI_BOOT_SECTOR_FLAG (0x4F)
- #define CFI_BOTTOM_BOOT (0x02)
- #define CFI_TOP_BOOT (0x03)
- #define CFI_NO_COMMAND_SET (0)
- #define CFI_INTEL_EXTENDED_COMMAND_SET (1)
- #define CFI_AMD_STANDARD_COMMAND_SET (2)
- #define CFI_INTEL_STANDARD_COMMAND_SET (3)
- #define CFI_AMD_EXTENDED_COMMAND_SET (4)
- #define CFI_SST_COMMAND_SET (0x0701)
- #define CFI_INTEL_ERASE_COMMAND_SETUP (0x20)
- #define CFI_INTEL_ERASE_COMMAND_CONFIRM (0xD0)
- #define CFI_INTEL_STATUS_BUSY (0x80)
- #define CFI_INTEL_RESET_TO_READ (0xFF)
- #define CFI_INTEL_READ_STATUS (0x70)
- #define CFI_INTEL_CLEAR_STATUS (0x50)
- #define CFI_INTEL_COMMAND_ERROR (0x30)
- #define CFI_INTEL_WRITE_WORD (0x40)
- #define CFI_INTEL_WRITE_BUFFER_SETUP (0xE8)
- #define CFI_INTEL_WRITE_CONFIRM (0xD0)
- #define CFI_INTEL_READ_IDENTIFIER_CODES (0x90)
- #define CFI_AMD_COMMAND_PROGRAM (0xA0)
- #define CFI_AMD_COMMAND_UNLOCK_BYPASS (0x20)
- #define CFI_AMD_COMMAND_ERASE (0x80)
- #define CFI_AMD_UNLOCK_BYPASS_RESET_1 (0x90)
- #define CFI_AMD_UNLOCK_BYPASS_RESET_2 (0x00)
- #define CFI_AMD_ERASE_COMMAND_CHIP (0x10)
- #define CFI_AMD_ERASE_COMMAND_SECTOR (0x30)
- #define CFI_AMD_DQ7_BIT_MASK (0x80)
- #define CFI_AMD_TOGGLE_BIT_MASK (0x40)
- #define CFI_AMD_TIMEOUT_BIT_MASK (0x20)
- INT32 CFIAMDBusy(T_CFIRomDevice *this);
- INT32 CFIAMDEraseChip(T_CFIRomDevice *this, UINT32 blocking);
- INT32 CFIAMDEraseSector(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT32 blocking);
- INT32 CFIAMDExtendedProgram(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT8 *sourceData, UINT32 numBytes);
- INT32 CFIAMDExtendedProgram(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT8 *sourceData, UINT32 numBytes);
- void CFIAMDIDCodesEntry(T_CFIRomDevice *this);
- INT32 CFIAMDProgram(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT8 *sourceData, UINT32 numBytes);
- void CFIAMDReset(T_CFIRomDevice *this);
- INT32 CFIIntelBusy(T_CFIRomDevice *this);
- INT32 CFIIntelEraseSector(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT32 block);
- INT32 CFIIntelExtendedProgram(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT8 *sourceData, UINT32 numBytes);
- void CFIIntelIDCodesEntry(T_CFIRomDevice *this);
- INT32 CFIIntelProgram(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT8 *sourceData, UINT32 numBytes);
- void CFIIntelReset(T_CFIRomDevice *this);
- UINT16 CFISetEndian(UINT16 value);
- static UINT32 EXCStartCriticalSection(void)
- {
- KB_OSPTaskDelay(1);
- return 0;
- }
- static void EXCEndCriticalSection(UINT32 State)
- {
- State = State;
- KB_OSPTaskDelay(1);
- }
- /****************************************************************************
- ** Functions
- ****************************************************************************/
- INT32 CFIIdentify(UINT16 *intRomAddress, T_CFIRomDevice *romDevice)
- {
- UINT32 numEraseBlockRegions;
- UINT32 index;
- UINT32 whichSector, numSectors, sectorSize;
- UINT32 sectorBaseAddress;
- UINT32 boolInvertGeometry;
- UINT32 bootSectorFlag;
- UINT32 irqState;
-
- irqState = EXCStartCriticalSection();
-
- /*
- ** Issue CFI Query command by writing 0x98 to address 0x55
- */
- ((WORDREG)intRomAddress)[CFI_QUERY_ADDRESS] = CFI_QUERY_COMMAND;
-
- if (((((WORDREG)intRomAddress)[CFI_QUERY_Q] & 0xFF) != 'Q') ||
- ((((WORDREG)intRomAddress)[CFI_QUERY_R] & 0xFF) != 'R') ||
- ((((WORDREG)intRomAddress)[CFI_QUERY_Y] & 0xFF) != 'Y'))
- {
- /*
- ** This doesn't appear to be a CFI ROM. However, there is a
- ** chance that we have an SST device. SST devices implement the CFI
- ** standard in a proprietary way. Test for this first before
- ** we give up.
- */
- ((WORDREG)intRomAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)intRomAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)intRomAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_QUERY_COMMAND;
-
- if (((((WORDREG)intRomAddress)[CFI_QUERY_Q] & 0xFF) != 'Q') ||
- ((((WORDREG)intRomAddress)[CFI_QUERY_R] & 0xFF) != 'R') ||
- ((((WORDREG)intRomAddress)[CFI_QUERY_Y] & 0xFF) != 'Y'))
- {
- /*
- ** Not a CFI ROM, so return.
- */
- romDevice->baseAddress = 0;
- EXCEndCriticalSection(irqState);
- return FAILURE;
- }
- }
-
- /*
- ** Read the rom size.
- */
- romDevice->romSize = (1 << ((WORDREG)intRomAddress)[CFI_2N_DEVICE_SIZE]);
-
- /*
- ** The rom base address mask will be the same as the
- ** inversion of the rom size -1. E.g. A 64 MBit rom
- ** will have a rom size of 0x800000, this makes the
- ** base address mask 0xFF800000.
- */
- romDevice->romBaseMask = ~(romDevice->romSize - 1);
-
- /*
- ** We should already have the ROM base address, but calculate
- ** it anyway.
- */
- romDevice->baseAddress = ((UINT32)intRomAddress & romDevice->romBaseMask);
-
- /*
- ** Find the supported command set.
- */
- romDevice->commandSet = (0xFF & ((WORDREG)romDevice->baseAddress)[CFI_VENDOR_COMMAND_SET]);
- romDevice->commandSet |= (0xFF & ((WORDREG)romDevice->baseAddress)[CFI_VENDOR_COMMAND_SET+1]) << 8;
-
- /*
- ** Read the number of erase block regions.
- */
- numEraseBlockRegions = ((WORDREG)(romDevice->baseAddress))[CFI_NUM_ERASE_BLOCK_REGIONS];
-
- /*
- ** For each erase block region read the details on the sectors (blocks)
- ** contained in it and expand to fill the romDevice structure.
- */
- whichSector = 0;
-
- for(index=0; index < numEraseBlockRegions; index++)
- {
- numSectors = (0xFF & ((WORDREG)(romDevice->baseAddress))[CFI_ERASE_BLOCK_REGION_INFO + (4 * index) + CFI_NUM_BLOCKS_IN_REGION_LO]);
- numSectors |= (0xFF & ((WORDREG)(romDevice->baseAddress))[CFI_ERASE_BLOCK_REGION_INFO + (4 * index) + CFI_NUM_BLOCKS_IN_REGION_HI]) << 8;
- numSectors++;
-
- sectorSize = (0xFF & ((WORDREG)(romDevice->baseAddress))[CFI_ERASE_BLOCK_REGION_INFO + (4 * index) + CFI_256X_BLOCK_SIZE_LO]);
- sectorSize |= (0xFF & ((WORDREG)(romDevice->baseAddress))[CFI_ERASE_BLOCK_REGION_INFO + (4 * index) + CFI_256X_BLOCK_SIZE_HI]) << 8;
- sectorSize *= 256;
-
- do
- {
- romDevice->sectorSize[whichSector++] = sectorSize;
- numSectors--;
- }
- while(numSectors > 0 );
- }
- romDevice->numSectors = whichSector;
-
- /*
- ** AMD and Fujitsu always list the device geometry for bottom boot devices.
- ** This then has to be inverted for top boot devices. Knowing if a device
- ** is top boot is an issue. For some devices you can read a CFI register,
- ** for others it has to be determined based on the device ID.
- */
- bootSectorFlag = ((WORDREG)(romDevice->baseAddress))[CFI_BOOT_SECTOR_FLAG];
- boolInvertGeometry = (bootSectorFlag == CFI_TOP_BOOT);
-
- /*
- ** Read max write buffer size.
- */
- romDevice->writeBufferDepth = (1 << ((WORDREG)(romDevice->baseAddress))[CFI_2N_MAX_BUFFER_BYTES]);
-
- /*
- ** Determine the programming algorithms to use and write the
- ** relevant function pointers to the romDevice structure.
- */
- switch (romDevice->commandSet)
- {
- case CFI_INTEL_EXTENDED_COMMAND_SET:
- romDevice->Busy = CFIIntelBusy;
- romDevice->Reset = CFIIntelReset;
- romDevice->IDCodesEntry = CFIIntelIDCodesEntry;
- romDevice->Program = CFIIntelExtendedProgram;
- romDevice->EraseSector = CFIIntelEraseSector;
- break;
- case CFI_INTEL_STANDARD_COMMAND_SET:
- romDevice->Busy = CFIIntelBusy;
- romDevice->Reset = CFIIntelReset;
- romDevice->IDCodesEntry = CFIIntelIDCodesEntry;
- romDevice->Program = CFIIntelProgram;
- romDevice->EraseSector = CFIIntelEraseSector;
- break;
-
- case CFI_AMD_STANDARD_COMMAND_SET:
- romDevice->Busy = CFIAMDBusy;
- romDevice->Reset = CFIAMDReset;
- romDevice->IDCodesEntry = CFIAMDIDCodesEntry;
- romDevice->Program = CFIAMDProgram;
- romDevice->EraseSector = CFIAMDEraseSector;
- break;
- case CFI_AMD_EXTENDED_COMMAND_SET:
- case CFI_SST_COMMAND_SET:
- romDevice->Busy = CFIAMDBusy;
- romDevice->Reset = CFIAMDReset;
- romDevice->IDCodesEntry = CFIAMDIDCodesEntry;
- romDevice->Program = CFIAMDExtendedProgram;
- romDevice->EraseSector = CFIAMDEraseSector;
- break;
- default:
- /* {
- UINT8 string[9];
- SUIPutMessage("nbaseAddress: 0x");
- APPIntToHexString(romDevice->baseAddress, string);
- SUIPutMessage(string);
- SUIPutMessage("tromSize: 0x");
- APPIntToHexString(romDevice->romSize, string);
- SUIPutMessage(string);
- SUIPutMessage("ncommandSet: 0x");
- APPIntToHexString(romDevice->commandSet, string);
- SUIPutMessage(string);
- SUIPutMessage("nnumSectors: 0x");
- APPIntToHexString(romDevice->numSectors, string);
- SUIPutMessage(string);
- SUIPutMessage("n0x13: 0x");
- APPIntToHexString(((WORDREG)romDevice->baseAddress)[CFI_VENDOR_COMMAND_SET], string);
- SUIPutMessage(string);
- SUIPutMessage("t0x14: 0x");
- APPIntToHexString(((WORDREG)romDevice->baseAddress)[CFI_VENDOR_COMMAND_SET + 1], string);
- SUIPutMessage(string);
- } */
- /*
- ** Put the ROM back into read array mode and return.
- */
- CFIAMDReset(romDevice);
- CFIIntelReset(romDevice);
-
- EXCEndCriticalSection(irqState);
- return(FAILURE);
- }
-
- /*
- ** Issue the read identifier codes command.
- */
- romDevice->Reset(romDevice);
- romDevice->IDCodesEntry(romDevice);
-
- /*
- ** Read the manufacturer and device id.
- */
- romDevice->manufacturerID = ((WORDREG)(romDevice->baseAddress))[CFI_MANUF_ID];
- romDevice->deviceID = ((WORDREG)(romDevice->baseAddress))[CFI_DEVICE_ID];
-
- /*
- ** Set the name parameter of the ROM.
- **
- ** We also use this point to catch the special case for AMD top boot
- ** ROMs where the device geometry has to be inverted.
- */
- switch (romDevice->manufacturerID)
- {
- case CFI_MANUF_AMD:
- switch (romDevice->deviceID)
- {
- case CFI_DEVICE_AM29LV400BT:
- romDevice->name = "AMD AM29LV400BT";
- break;
- case CFI_DEVICE_AM29LV400BB:
- romDevice->name = "AMD AM29LV400BB";
- break;
- case CFI_DEVICE_AM29LV800BT:
- romDevice->name = "AMD AM29LV800BT";
- break;
- case CFI_DEVICE_AM29LV800BB:
- romDevice->name = "AMD AM29LV800BB";
- break;
- case CFI_DEVICE_AM29LV160DB:
- romDevice->name = "AMD AM29LV160DB";
- break;
- case CFI_DEVICE_AM29LV160DT:
- romDevice->name = "AMD AM29LV160DT";
- boolInvertGeometry = TRUE; /* Special case */
- break;
- case CFI_DEVICE_AM29LV320DT:
- romDevice->name = "AMD AM29LV320DT";
- break;
- case CFI_DEVICE_AM29LV320DB:
- romDevice->name = "AMD AM29LV320DB";
- break;
- case CFI_DEVICE_AM29LV640DU:
- romDevice->name = "AMD AM29LV640DU";
- break;
- case CFI_DEVICE_AM29DL322DT:
- romDevice->name = "AMD AM29DL322DT";
- break;
- case CFI_DEVICE_AM29DL322DB:
- romDevice->name = "AMD AM29DL322DB";
- break;
- case CFI_DEVICE_AM29DL323DT:
- romDevice->name = "AMD AM29DL323DT";
- break;
- case CFI_DEVICE_AM29DL323DB:
- romDevice->name = "AMD AM29DL323DB";
- break;
- case CFI_DEVICE_AM29DL324DT:
- romDevice->name = "AMD AM29DL324DT";
- break;
- case CFI_DEVICE_AM29DL324DB:
- romDevice->name = "AMD AM29DL324DB";
- break;
- default:
- romDevice->name = "Unknown AMD";
- break;
- }
- break;
-
- case CFI_MANUF_FUJITSU:
- switch (romDevice->deviceID)
- {
- case CFI_DEVICE_MBM29LV160BE:
- romDevice->name = "Fujitsu MBM29LV160BE";
- break;
- case CFI_DEVICE_MBM29LV160TE:
- romDevice->name = "Fujitsu MBM29LV160TE";
- boolInvertGeometry = TRUE; /* Special case */
- break;
- case CFI_DEVICE_MBM29DL32TF_BF:
- if(boolInvertGeometry)
- {
- romDevice->name = "Fujitsu MBM29DL32TF";
- }
- else
- {
- romDevice->name = "Fujitsu MBM29DL32BF";
- }
- break;
- default:
- romDevice->name = "Unknown Fujitsu";
- break;
- }
- break;
-
- case CFI_MANUF_INTEL:
- switch (romDevice->deviceID)
- {
- case CFI_DEVICE_28F800C3T:
- romDevice->name = "Intel 28F800C3-T";
- break;
- case CFI_DEVICE_28F800C3B:
- romDevice->name = "Intel 28F800C3-B";
- break;
- case CFI_DEVICE_28F160C3T:
- romDevice->name = "Intel 28F160C3-T";
- break;
- case CFI_DEVICE_28F160C3B:
- romDevice->name = "Intel 28F160C3-B";
- break;
- case CFI_DEVICE_28F320C3T:
- romDevice->name = "Intel 28F320C3-T";
- break;
- case CFI_DEVICE_28F320C3B:
- romDevice->name = "Intel 28F320C3-B";
- break;
- case CFI_DEVICE_28F640C3T:
- romDevice->name = "Intel 28F640C3-T";
- break;
- case CFI_DEVICE_28F640C3B:
- romDevice->name = "Intel 28F640C3-B";
- break;
- case CFI_DEVICE_28F128J3A:
- romDevice->name = "Intel 28F128J3A";
- break;
- case CFI_DEVICE_28F320J3A:
- romDevice->name = "Intel 28F320J3A";
- break;
- case CFI_DEVICE_28F640J3A:
- romDevice->name = "Intel 28F640J3A";
- break;
- default:
- romDevice->name = "Unknown Intel";
- break;
- }
- break;
-
- case CFI_MANUF_SHARP:
- switch (romDevice->deviceID)
- {
- case CFI_DEVICE_LH28F800BJ:
- romDevice->name = "Sharp LH28F800BJ";
- break;
- case CFI_DEVICE_LH28F160BJ:
- romDevice->name = "Sharp LH28F160BJ";
- break;
- case CFI_DEVICE_LH28F320BJ:
- romDevice->name = "Sharp LH28F320BJ";
- break;
- case CFI_DEVICE_LH28F160S3:
- romDevice->name = "Sharp LH28F160S3";
- break;
- default:
- romDevice->name = "Unknown Sharp";
- break;
- }
- break;
-
- case CFI_MANUF_ST:
- switch (romDevice->deviceID)
- {
- case CFI_DEVICE_M29W160DT:
- romDevice->name = "ST M29W160DT";
- break;
- case CFI_DEVICE_M29W160DB:
- romDevice->name = "ST M29W160DB";
- break;
- case CFI_DEVICE_M29W320DT:
- romDevice->name = "ST M29W320DT";
- break;
- case CFI_DEVICE_M29W320DB:
- romDevice->name = "ST M29W320DB";
- break;
- case CFI_DEVICE_M29W640FT:
- romDevice->name = "ST M29W640FT";
- break;
- default:
- romDevice->name = "Unknown ST";
- break;
- }
- break;
-
- case CFI_MANUF_SST:
- switch (romDevice->deviceID)
- {
- case CFI_DEVICE_SST39xF200A:
- romDevice->name = "SST SST39LF200/SST39VF200";
- break;
- case CFI_DEVICE_SST39xF400A:
- romDevice->name = "SST SST39LF400/SST39VF400";
- break;
- case CFI_DEVICE_SST39xF800A:
- romDevice->name = "SST SST39LF800/SST39VF800";
- break;
- case CFI_DEVICE_SST39xF160:
- romDevice->name = "SST SST39LF160/SST39VF160";
- break;
- default:
- romDevice->name = "Unknown SST";
- break;
- }
- break;
-
- case CFI_MANUF_TOSHIBA:
- switch (romDevice->deviceID)
- {
- case CFI_DEVICE_TC58FVT160:
- romDevice->name = "Toshiba TC58FVT160";
- break;
- case CFI_DEVICE_TC58FVB160:
- romDevice->name = "Toshiba TC58FVB160";
- break;
- case CFI_DEVICE_TC58FVT321:
- romDevice->name = "Toshiba TC58FVT321";
- break;
- case CFI_DEVICE_TC58FVB321:
- romDevice->name = "Toshiba TC58FVB321";
- break;
- case CFI_DEVICE_TC58FVT641:
- romDevice->name = "Toshiba TC58FVT641";
- break;
- case CFI_DEVICE_TC58FVB641:
- romDevice->name = "Toshiba TC58FVB641";
- break;
- default:
- romDevice->name = "Unknown Toshiba";
- break;
- }
- break;
-
- default:
- romDevice->name = "Unknown Manufacturer";
- break;
- }
-
- /*
- ** Specifically for AMD and Fujitsu ROMs invert the device geometry
- ** if required.
- */
- if (((romDevice->manufacturerID == CFI_MANUF_AMD) || (romDevice->manufacturerID == CFI_MANUF_FUJITSU)) && (boolInvertGeometry != FALSE))
- {
- for(index=0; index < ((romDevice->numSectors - 1) / 2); index++)
- {
- sectorSize = romDevice->sectorSize[index];
- romDevice->sectorSize[index] = romDevice->sectorSize[romDevice->numSectors - index - 1];
- romDevice->sectorSize[romDevice->numSectors - index - 1] = sectorSize;
- }
- }
-
- /*
- ** Determine what sectors are protected and get each sector base address.
- */
- sectorBaseAddress = romDevice->baseAddress;
- for (index=0; index < (romDevice->numSectors) ; index++)
- {
- romDevice->sector[index] = ((WORDREG)sectorBaseAddress)[CFI_SECTOR_PROTECT] & 0x1;
- romDevice->sectorAddr[index] = sectorBaseAddress;
- sectorBaseAddress += romDevice->sectorSize[index];
- }
-
- /*
- ** Put the ROM back into read array mode and return.
- */
- romDevice->Reset(romDevice);
-
- EXCEndCriticalSection(irqState);
- return(SUCCESS);
- }
- /****************************************************************************
- ** Function CFIAMDBusy(): This function tests to see if a FLASH ROM command is
- ** currently being executed. It will also test if a command has failed.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- **
- ** Outputs: None
- **
- ** Returns: TRUE if the ROM is busy.
- ** FALSE if the ROM is not busy.
- ** FAILURE if the command failed.
- ****************************************************************************/
- INT32 CFIAMDBusy(T_CFIRomDevice *this)
- {
- UINT16 toggleOdd, toggleEven;
- INT32 nret;
- UINT32 irqState;
-
- irqState = EXCStartCriticalSection();
-
- /*
- ** If the toggle bit is still toggling then the ROM is still
- ** attempting to execute a command.
- */
- toggleOdd = (*((WORDREG)this->baseAddress) & CFI_AMD_TOGGLE_BIT_MASK);
- toggleEven = (*((WORDREG)this->baseAddress) & CFI_AMD_TOGGLE_BIT_MASK);
-
- if (toggleOdd != toggleEven)
- {
- /*
- ** The ROM is busy so set the return value to TRUE.
- ** This will change if the command has timed out..
- */
- nret = TRUE;
-
- /*
- ** Test to see if the command has timed out.
- */
- if ((*((WORDREG)this->baseAddress) & CFI_AMD_TIMEOUT_BIT_MASK) != 0)
- {
- /*
- ** Just because the operation has timed out
- ** does not necessarily mean that it has failed.
- ** Test to see if it has succeeded before returning.
- ** If the toggle bit is still toggling then it has failed.
- */
- toggleOdd = (*((WORDREG)this->baseAddress) & CFI_AMD_TOGGLE_BIT_MASK);
- toggleEven = (*((WORDREG)this->baseAddress) & CFI_AMD_TOGGLE_BIT_MASK);
-
- if (toggleOdd != toggleEven)
- {
- /*
- ** Put the ROM back into normal read mode.
- */
- CFIAMDReset(this);
-
- /*
- ** Return FAILURE.
- */
- nret = FAILURE;
- }
- else
- {
- /*
- ** Return FALSE as the ROM is no longer busy.
- */
- nret = FALSE;
- }
- }
- }
- else
- {
- /*
- ** Return FALSE as the ROM is no longer busy.
- */
- nret = FALSE;
- }
-
- EXCEndCriticalSection(irqState);
- return nret;
- }
- /****************************************************************************
- ** Function CFIAMDEraseChip(): This function will erase all unprotected sectors
- ** of the specified AMD FLASH ROM. This is function can be either blocking
- ** or non-blocking. If the blocking mode is used then this function will not
- ** return control until either the ROM is erased or an error occurs. If a
- ** non-blocking mode is used then the CFIAMDBusy() should be used to poll for
- ** completion.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- ** block, CFI_BLOCKING if this function should block waiting
- ** for completion, or CFI_NON_BLOCKING if this function should
- ** return immediately after initiating the command.
- **
- ** Outputs: None
- **
- ** Returns: SUCCESS if the ROM is successfully erased.
- ** FAILURE if this function is not running in RAM, or the
- ** erase failed.
- ****************************************************************************/
- INT32 CFIAMDEraseChip(T_CFIRomDevice *this, UINT32 blocking)
- {
- INT32 nret;
- INT32 busy;
- UINT32 irqState;
-
- irqState = EXCStartCriticalSection();
-
- /*
- ** Enter the chip erase command.
- ** Pre-amble first, then erase command, then pre-amble again,
- ** then chip erase command.
- */
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_TYPE] = CFI_AMD_COMMAND_ERASE;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_TYPE] = CFI_AMD_ERASE_COMMAND_CHIP;
-
- /*
- ** If this function was called in the non-blocking mode then
- ** return immediately, otherwise wait for the erase command
- ** to be completed.
- */
- if (blocking == CFI_BLOCKING)
- {
- /*
- ** Wait for the erase command to complete. CFIAMDBusy() will
- ** also report if the operation failed.
- */
- while ((busy = CFIAMDBusy(this)) == TRUE);
- if (busy == FAILURE)
- {
- nret = FAILURE;
- }
- else
- {
- nret = SUCCESS;
- }
- }
- else
- {
- nret = SUCCESS;
- }
-
- EXCEndCriticalSection(irqState);
- return nret;
- }
- /****************************************************************************
- ** Function CFIAMDEraseSector(): This function will erase the specified sector
- ** of an AMD FLASH ROM. This is function can be either blocking or
- ** non-blocking. If the blocking mode is used then this function will not
- ** return control until either the sector is erased or an error occurs. If a
- ** non-blocking mode is used then the CFIAMDBusy() should be used to poll for
- ** completion.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- ** targetAddress, an address inside the sector to be erased.
- ** blocking, CFI_BLOCKING or CFI_NON_BLOCKING
- **
- ** Outputs: None
- **
- ** Returns: SUCCESS if the ROM is successfully erased.
- ** FAILURE if this function is not running in RAM, or the
- ** erase failed.
- ****************************************************************************/
- INT32 CFIAMDEraseSector(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT32 blocking)
- {
- INT32 nret;
- INT32 busy;
- UINT32 irqState;
-
- irqState = EXCStartCriticalSection();
-
- /*
- ** Enter sector erase mode.
- ** Pre-amble first, then erase command, then pre-amble again,
- ** then sector to erase.
- */
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_TYPE] = CFI_AMD_COMMAND_ERASE;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- *((WORDREG)targetAddress) = CFI_AMD_ERASE_COMMAND_SECTOR;
-
- /*
- ** If this function was called in the non-blocking mode then
- ** return immediately, otherwise wait for the erase command
- ** to be completed.
- */
- if (blocking == CFI_BLOCKING)
- {
- /*
- ** Wait for the erase command to complete. CFIAMDBusy() will
- ** also report if the operation failed.
- */
- while ((busy = CFIAMDBusy(this)) == TRUE);
- if (busy == FAILURE)
- {
- nret = FAILURE;
- }
- else
- {
- nret = SUCCESS;
- }
- }
- else
- {
- nret = SUCCESS;
- }
-
- EXCEndCriticalSection(irqState);
- return nret;
- }
- /****************************************************************************
- ** Function CFIAMDExtendedProgram(): This function will program the
- ** specified area of an AMD FLASH ROM. This is a blocking function and will
- ** not return control until either the programming is complete or an error
- ** occurs.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- ** targetAddress, the start address to program to in the ROM.
- ** sourceData, a pointer to the start of the data to be
- ** programmed.
- ** numBytes, the number of bytes to be programmed.
- **
- ** Outputs: None
- **
- ** Returns: SUCCESS if the programming is successful.
- ** FAILURE if this function is not running in RAM, or the
- ** programming failed. The programming is likely to fail
- ** if an attempt is made to program an area of memory that
- ** has not been erased. Specifically if an attempt is made
- ** to change a 0 to a 1.
- ****************************************************************************/
- INT32 CFIAMDExtendedProgram(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT8 *sourceData, UINT32 numBytes)
- {
- UINT32 i=0;
- UINT16 tempWord;
- UINT16 *writeAddress;
- UINT32 irqState;
-
- irqState = EXCStartCriticalSection();
-
- /************************************************************************
- ** Mis-aligned write detection and handling.
- ************************************************************************/
-
- /*
- ** Our FLASH ROM is a 16-bit device, however we may be asked to write an
- ** odd number of bytes, or the target address may not be on a 16-bit
- ** boundary. If this is the case write use read/modify/write cycles to
- ** write the misaligned data.
- */
-
- /*
- ** If the start address is mis-aligned, write the first
- ** byte to align the start address.
- */
- if (((UINT32)targetAddress & 1) != 0)
- {
- /*
- ** Calculate what to write to where, i.e. do the read and modify.
- ** The function parameters will also be adapted ready for the
- ** main body of this function.
- */
- targetAddress = (UINT16 *)((UINT32)targetAddress & ~1);
- tempWord = targetAddress[0] & CFISetEndian(0xFF00); // We are masking off the lowest addressed byte which is a different part of the 16-bit word on big and little endian machines.
- tempWord |= CFISetEndian((UINT16)sourceData[0]);
-
- writeAddress = targetAddress;
- targetAddress++;
- numBytes--;
- sourceData++;
-
- /*
- ** Write the data.
- */
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_TYPE] = CFI_AMD_COMMAND_PROGRAM;
- *((WORDREG)writeAddress) = tempWord;
-
- /*
- ** Poll for the programming completion.
- */
- while ( (*((WORDREG)writeAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Test to see if the programming operation
- ** has timed out.
- */
- if ((*((WORDREG)targetAddress) & CFI_AMD_TIMEOUT_BIT_MASK) != 0)
- {
- /*
- ** Just because the programming operation has timed
- ** out does not necessarily mean that it has failed.
- ** If DQ7 (data bit 7) is still the inverse of the data
- ** being programmed then the operation has failed.
- */
- if ( (*((WORDREG)targetAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Reset the FLASH ROM back to read mode.
- */
- CFIAMDReset(this);
-
- /*
- ** Test to see if the word actually programmed.
- */
- if(*((WORDREG)writeAddress) == tempWord)
- {
- break;
- }
-
- /*
- ** Return FAILURE, as the programming failed.
- ** The most likely reason being that an attempt
- ** was made to program a '0' to a '1'.
- */
- EXCEndCriticalSection(irqState);
- return FAILURE;
- }
- }
- }
- }
-
- /*
- ** If there is now an odd number of bytes to write, the last
- ** byte has to be written to align the data length.
- */
- if ((numBytes & 1) != 0)
- {
- tempWord = targetAddress[((numBytes-1) >> 1)] & CFISetEndian(0x00FF);
- tempWord |= CFISetEndian((UINT16)(sourceData[(numBytes-1)] << 8));
- writeAddress = &(targetAddress[((numBytes-1) >> 1)]);
- numBytes--;
-
- /*
- ** Write the data.
- */
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_TYPE] = CFI_AMD_COMMAND_PROGRAM;
- *((WORDREG)writeAddress) = tempWord;
-
- /*
- ** Poll for the programming completion.
- */
- while ( (*((WORDREG)writeAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Test to see if the programming operation
- ** has timed out.
- */
- if ((*((WORDREG)targetAddress) & CFI_AMD_TIMEOUT_BIT_MASK) != 0)
- {
- /*
- ** Just because the programming operation has timed
- ** out does not necessarily mean that it has failed.
- ** If DQ7 (data bit 7) is still the inverse of the data
- ** being programmed then the operation has failed.
- */
- if ( (*((WORDREG)targetAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Reset the FLASH ROM back to read mode.
- */
- CFIAMDReset(this);
-
- /*
- ** Test to see if the word actually programmed.
- */
- if(*((WORDREG)writeAddress) == tempWord)
- {
- break;
- }
-
- /*
- ** Return FAILURE, as the programming failed.
- ** The most likely reason being that an attempt
- ** was made to program a '0' to a '1'.
- */
- EXCEndCriticalSection(irqState);
- return FAILURE;
- }
- }
- }
- }
-
- /************************************************************************
- ** Aligned writes.
- ************************************************************************/
-
- /*
- ** Enter unlock bypass mode.
- ** Pre-amble first, then unlock bypass command.
- */
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_TYPE] = CFI_AMD_COMMAND_UNLOCK_BYPASS;
-
- while(i < numBytes)
- {
- /*
- ** Issue the program command
- */
- ((WORDREG)this->baseAddress)[0x0] = CFI_AMD_COMMAND_PROGRAM;
-
- /*
- ** Write the word.
- */
- tempWord = CFISetEndian((UINT16)((sourceData[i]<<8) | sourceData[i+1]));
- *((WORDREG)targetAddress) = tempWord;
-
- /*
- ** Poll for the programming completion.
- */
- while ( (*((WORDREG)targetAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Test to see if the programming operation
- ** has timed out.
- */
- if ((*((WORDREG)targetAddress) & CFI_AMD_TIMEOUT_BIT_MASK) != 0)
- {
- /*
- ** Just because the programming operation has timed
- ** out does not necessarily mean that it has failed.
- ** If DQ7 (data bit 7) is still the inverse of the data
- ** being programmed then the operation has failed.
- */
- if ( (*((WORDREG)targetAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Reset the FLASH ROM back to read mode.
- */
- *((WORDREG)this->baseAddress) = CFI_AMD_UNLOCK_BYPASS_RESET_1;
- *((WORDREG)this->baseAddress) = CFI_AMD_UNLOCK_BYPASS_RESET_2;
-
- /*
- ** Return FAILURE, as the programming failed.
- ** The most likely reason being that an attempt
- ** was made to program a '0' to a '1'.
- */
- EXCEndCriticalSection(irqState);
- return FAILURE;
- }
- }
- }
-
- /*
- ** Increment the source and target addresses.
- */
- targetAddress++;
- i += 2;
- }
-
- /*
- ** Reset the FLASH ROM back to read mode.
- */
- *((WORDREG)this->baseAddress) = CFI_AMD_UNLOCK_BYPASS_RESET_1;
- *((WORDREG)this->baseAddress) = CFI_AMD_UNLOCK_BYPASS_RESET_2;
-
- /*
- ** Return SUCCESS.
- */
- EXCEndCriticalSection(irqState);
- return SUCCESS;
- }
- /****************************************************************************
- ** Function CFIAMDIDCodesEntry(): This function places an AMD compatible
- ** FLASH ROM in the read indentify codes mode,
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- **
- ** Outputs: None
- **
- ** Returns: Nothing.
- ****************************************************************************/
- void CFIAMDIDCodesEntry(T_CFIRomDevice *this)
- {
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_IDENTIFIER_CODES_ADDRESS] = CFI_IDENTIFIER_CODES_COMMAND;
- }
- /****************************************************************************
- ** Function CFIAMDProgram(): This function will program the
- ** specified area of an AMD FLASH ROM. This is a blocking function and will
- ** not return control until either the programming is complete or an error
- ** occurs.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- ** targetAddress, the start address to program to in the ROM.
- ** sourceData, a pointer to the start of the data to be
- ** programmed.
- ** numBytes, the number of bytes to be programmed.
- **
- ** Outputs: None
- **
- ** Returns: SUCCESS if the programming is successful.
- ** FAILURE if this function is not running in RAM, or the
- ** programming failed. The programming is likely to fail
- ** if an attempt is made to program an area of memory that
- ** has not been erased. Specifically if an attempt is made
- ** to change a 0 to a 1.
- ****************************************************************************/
- INT32 CFIAMDProgram(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT8 *sourceData, UINT32 numBytes)
- {
- UINT32 i=0;
- UINT16 tempWord;
- UINT16 *writeAddress;
- UINT32 irqState;
-
- irqState = EXCStartCriticalSection();
-
- /************************************************************************
- ** Mis-aligned write detection and handling.
- ************************************************************************/
-
- /*
- ** Our FLASH ROM is a 16-bit device, however we may be asked to write an
- ** odd number of bytes, or the target address may not be on a 16-bit
- ** boundary. If this is the case write use read/modify/write cycles to
- ** write the misaligned data.
- */
-
- /*
- ** If the start address is mis-aligned, write the first
- ** byte to align the start address.
- */
- if (((UINT32)targetAddress & 1) != 0)
- {
- /*
- ** Calculate what to write to where, i.e. do the read and modify.
- ** The function parameters will also be adapted ready for the
- ** main body of this function.
- */
- targetAddress = (UINT16 *)((UINT32)targetAddress & ~1);
- tempWord = targetAddress[0] & CFISetEndian(0xFF00); // We are masking off the lowest addressed byte which is a different part of the 16-bit word on big and little endian machines.
- tempWord |= CFISetEndian((UINT16)sourceData[0]);
-
- writeAddress = targetAddress;
- targetAddress++;
- numBytes--;
- sourceData++;
-
- /*
- ** Write the data.
- */
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_TYPE] = CFI_AMD_COMMAND_PROGRAM;
- *((WORDREG)writeAddress) = tempWord;
-
- /*
- ** Poll for the programming completion.
- */
- while ( (*((WORDREG)writeAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Test to see if the programming operation
- ** has timed out.
- */
- if ((*((WORDREG)targetAddress) & CFI_AMD_TIMEOUT_BIT_MASK) != 0)
- {
- /*
- ** Just because the programming operation has timed
- ** out does not necessarily mean that it has failed.
- ** If DQ7 (data bit 7) is still the inverse of the data
- ** being programmed then the operation has failed.
- */
- if ( (*((WORDREG)targetAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Reset the FLASH ROM back to read mode.
- */
- CFIAMDReset(this);
-
- /*
- ** Test to see if the word actually programmed.
- */
- if(*((WORDREG)writeAddress) == tempWord)
- {
- break;
- }
-
- /*
- ** Return FAILURE, as the programming failed.
- ** The most likely reason being that an attempt
- ** was made to program a '0' to a '1'.
- */
- EXCEndCriticalSection(irqState);
- return FAILURE;
- }
- }
- }
- }
-
- /*
- ** If there is now an odd number of bytes to write, the last
- ** byte has to be written to align the data length.
- */
- if ((numBytes & 1) != 0)
- {
- tempWord = targetAddress[((numBytes-1) >> 1)] & CFISetEndian(0x00FF);
- tempWord |= CFISetEndian((UINT16)(sourceData[(numBytes-1)] << 8));
- writeAddress = &(targetAddress[((numBytes-1) >> 1)]);
- numBytes--;
-
- /*
- ** Write the data.
- */
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_TYPE] = CFI_AMD_COMMAND_PROGRAM;
- *((WORDREG)writeAddress) = tempWord;
-
- /*
- ** Poll for the programming completion.
- */
- while ( (*((WORDREG)writeAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Test to see if the programming operation
- ** has timed out.
- */
- //if ((*((WORDREG)targetAddress) & CFI_AMD_TIMEOUT_BIT_MASK) != 0)
- if ((*((WORDREG)writeAddress) & CFI_AMD_TIMEOUT_BIT_MASK) != 0)
- {
- /*
- ** Just because the programming operation has timed
- ** out does not necessarily mean that it has failed.
- ** If DQ7 (data bit 7) is still the inverse of the data
- ** being programmed then the operation has failed.
- */
- //if ( (*((WORDREG)targetAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- if ( (*((WORDREG)writeAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Reset the FLASH ROM back to read mode.
- */
- CFIAMDReset(this);
-
- /*
- ** Return FAILURE, as the programming failed.
- ** The most likely reason being that an attempt
- ** was made to program a '0' to a '1'.
- */
- EXCEndCriticalSection(irqState);
- return FAILURE;
- }
- }
- }
- }
-
- /************************************************************************
- ** Aligned writes.
- ************************************************************************/
- while(i < numBytes)
- {
- /*
- ** Write the data.
- */
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_1] = CFI_COMMAND_PREAMBLE_1_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_PREAMBLE_2] = CFI_COMMAND_PREAMBLE_2_DATA;
- ((WORDREG)this->baseAddress)[CFI_COMMAND_TYPE] = CFI_AMD_COMMAND_PROGRAM;
- tempWord = CFISetEndian((UINT16)((sourceData[i]<<8) | sourceData[i+1]));
- *((WORDREG)targetAddress) = tempWord;
- /*
- ** Poll for the programming completion.
- */
- while ( (*((WORDREG)targetAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Test to see if the programming operation
- ** has timed out.
- */
- if ((*((WORDREG)targetAddress) & CFI_AMD_TIMEOUT_BIT_MASK) != 0)
- {
- /*
- ** Just because the programming operation has timed
- ** out does not necessarily mean that it has failed.
- ** If DQ7 (data bit 7) is still the inverse of the data
- ** being programmed then the operation has failed.
- */
- if ( (*((WORDREG)targetAddress) & CFI_AMD_DQ7_BIT_MASK) !=
- (tempWord & CFI_AMD_DQ7_BIT_MASK) )
- {
- /*
- ** Reset the FLASH ROM back to read mode.
- */
- CFIAMDReset(this);
-
- /*
- ** Return FAILURE, as the programming failed.
- ** The most likely reason being that an attempt
- ** was made to program a '0' to a '1'.
- */
- EXCEndCriticalSection(irqState);
- return FAILURE;
- }
- }
- }
-
- /*
- ** Increment the source and target addresses.
- */
- targetAddress++;
- i += 2;
- }
-
- /*
- ** Reset the FLASH ROM back to read mode.
- */
- CFIAMDReset(this);
-
- /*
- ** Return SUCCESS.
- */
- EXCEndCriticalSection(irqState);
- return SUCCESS;
- }
- /****************************************************************************
- ** Function CFIAMDReset(): This function resets an AMD compatible FLASH ROM
- ** back to read array mode..
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- **
- ** Outputs: None
- **
- ** Returns: Nothing.
- ****************************************************************************/
- void CFIAMDReset(T_CFIRomDevice *this)
- {
- *(WORDREG)this->baseAddress = 0xF0;
- }
- /****************************************************************************
- ** Function CFIIntelBusy(): This function tests to see if a FLASH ROM command
- ** is currently being executed.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- **
- ** Outputs: None
- **
- ** Returns: TRUE if the ROM is busy.
- ** FALSE if the ROM is not busy.
- ****************************************************************************/
- INT32 CFIIntelBusy(T_CFIRomDevice *this)
- {
- return !(*((WORDREG)this->baseAddress) & CFI_INTEL_STATUS_BUSY);
- }
- /****************************************************************************
- ** Function CFIIntelEraseSector(): This function will erase the specified
- ** sector of an Intel FLASH ROM. This is function can be either blocking or
- ** non-blocking. If the blocking mode is used then this function will not
- ** return control until either the sector is erased or an error occurs. If a
- ** non-blocking mode is used then the CFIIntelBusy() should be used to poll for
- ** completion.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- ** targetAddress, an address inside the sector to be erased.
- ** blocking, CFI_BLOCKING or CFI_NON_BLOCKING
- **
- ** Outputs: None
- **
- ** Returns: SUCCESS if the ROM is successfully erased.
- ** FAILURE if this function is not running in RAM, or the
- ** erase failed.
- ****************************************************************************/
- INT32 CFIIntelEraseSector(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT32 blocking)
- {
- INT32 nret;
- UINT32 irqState;
-
- irqState = EXCStartCriticalSection();
-
- /*
- ** Enter sector erase mode.
- ** Block erase setup first, then block erase confirm.
- */
- *((WORDREG)targetAddress) = CFI_INTEL_ERASE_COMMAND_SETUP;
- *((WORDREG)targetAddress) = CFI_INTEL_ERASE_COMMAND_CONFIRM;
-
- /*
- ** If this function was called in the non-blocking mode then
- ** return immediately, otherwise wait for the erase command
- ** to be completed.
- */
- if (blocking == CFI_BLOCKING)
- {
- /*
- ** Wait for the erase command to be completed.
- */
- while (CFIIntelBusy(this));
-
- /*
- ** Test for an error.
- */
- if (*((WORDREG)targetAddress) != 0x80)
- {
- /*
- ** An error occurred. Clear the status register, put
- ** the device back into read mode and return.
- */
- *((WORDREG)this->baseAddress) = CFI_INTEL_CLEAR_STATUS;
- *((WORDREG)this->baseAddress) = CFI_INTEL_RESET_TO_READ;
-
- nret = FAILURE;
- }
- else
- {
- /*
- ** The erase command completed successfully. Put the
- ** device back into read mode and return.
- */
- CFIIntelReset(this);
-
- nret = SUCCESS;
- }
- }
- else
- {
- nret = SUCCESS;
- }
-
- EXCEndCriticalSection(irqState);
- return nret;
- }
- /****************************************************************************
- ** Function CFIIntelExtendedProgram(): This function will program the specified area
- ** of an Intel FLASH ROM. This is a blocking function and will not
- ** return control until either the programming is complete or an error occurs.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- ** targetAddress, the start address to program in the ROM.
- ** sourceData, a pointer to the start of the data to be
- ** programmed.
- ** numBytes, the number of bytes to be programmed.
- **
- ** Outputs: None
- **
- ** Returns: SUCCESS if the programming is successful.
- ** FAILURE if this function is not running in RAM, or the
- ** programming failed. The programming is likely to fail
- ** if an attempt is made to program an area of memory that
- ** has not been erased. Specifically if an attempt is made
- ** to change a 0 to a 1.
- ****************************************************************************/
- INT32 CFIIntelExtendedProgram(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT8 *sourceData, UINT32 numBytes)
- {
- UINT32 i=0, count;
- INT32 nret;
- UINT16 tempWord;
- UINT16 *sectorAddress;
- UINT32 irqState;
-
- irqState = EXCStartCriticalSection();
-
- /************************************************************************
- ** Mis-aligned write detection and handling.
- ************************************************************************/
-
- /*
- ** Our FLASH ROM is a 16-bit device, however we may be asked to write an
- ** odd number of bytes, or the target address may not be on a 16-bit
- ** boundary. If this is the case write use read/modify/write cycles to
- ** write the misaligned data.
- */
- if (((UINT32)targetAddress & 1) != 0)
- {
- /*
- ** The start address is mis-aligned, write the first
- ** byte to align the start address.
- */
-
- /*
- ** Read and modify the first word.
- */
- targetAddress = (UINT16 *)((UINT32)targetAddress & ~1);
- tempWord = targetAddress[0] & CFISetEndian(0xFF00);
- tempWord |= CFISetEndian(sourceData[0]);
-
- /*
- ** Write the word write command.
- */
- *((WORDREG)targetAddress) = CFI_INTEL_WRITE_WORD;
-
- /*
- ** Write the data
- */
- *((WORDREG)targetAddress) = tempWord;
-
- /*
- ** Poll for completion.
- */
- while (CFIIntelBusy(this));
-
- targetAddress++;
- numBytes--;
- sourceData++;
- }
-
- if ((numBytes & 1) != 0)
- {
- /*
- ** The data length is now mis-aligned, write the last byte
- ** to align to data length.
- */
-
- /*
- ** Put the device back into read mode.
- */
- *((WORDREG)this->baseAddress) = CFI_INTEL_RESET_TO_READ;
-
- tempWord = targetAddress[((numBytes-1) >> 1)] & CFISetEndian(0x00FF);
- tempWord |= CFISetEndian((UINT16)(sourceData[(numBytes-1)] << 8));
-
- /*
- ** Write the word write command.
- */
- ((WORDREG)targetAddress)[((numBytes-1) >> 1)] = CFI_INTEL_WRITE_WORD;
-
- /*
- ** Write the data
- */
- ((WORDREG)targetAddress)[((numBytes-1) >> 1)] = tempWord;
-
- /*
- ** Poll for completion.
- */
- while (CFIIntelBusy(this));
-
- numBytes--;
- }
-
- /************************************************************************
- ** Aligned writes over sector boundaries.
- ************************************************************************/
-
- /*
- ** We cannot do buffered writes over sector boundaries. This may
- ** happen if the targetAddress is not on a 32 byte boundary. If
- ** this is the case the first X bytes before a 32 byte boundary
- ** are written a word at a time. Buffered writes will then
- ** happen on sector boundaries.
- */
- if (((UINT32)targetAddress & 0x1F) != 0)
- {
- /*
- ** Calculate the number of words to write to
- ** get to a 32 bytes boundary. Also test to
- ** see that this isn't greater than the
- ** number of bytes to transfer.
- */
- count = (0x20 - ((UINT32)targetAddress & 0x1F)) >> 1;
- if (count > (numBytes >> 1))
- {
- count = numBytes >> 1;
- }
-
- /*
- ** Write the data.
- */
- while (count-- != 0)
- {
- /*
- ** Write the word write command.
- */
- *((WORDREG)targetAddress) = CFI_INTEL_WRITE_WORD;
-
- /*
- ** Write the data
- */
- *((WORDREG)targetAddress) = CFISetEndian((UINT16)((sourceData[i]<<8) | sourceData[i+1]));
-
- /*
- ** Poll for completion.
- */
- while (CFIIntelBusy(this));
-
- targetAddress++;
- i += 2;
- }
- }
-
- /************************************************************************
- ** Aligned writes not over sector boundaries.
- ************************************************************************/
-
- while(i < numBytes)
- {
- /*
- ** We write 16 bits at a time, so convert the byte count to a word
- ** count.
- */
- count = (numBytes - i) >> 1;
-
- /*
- ** We can only write a maximum of 32 bytes (16 words) at a time.
- */
- if (count > 16)
- {
- count = 16;
- }
-
- /*
- ** Store the sector address.
- */
- sectorAddress = targetAddress;
-
- /*
- ** Write the buffer setup command until it is accepted.
- */
- do
- {
- *((WORDREG)targetAddress) = CFI_INTEL_WRITE_BUFFER_SETUP;
- } while ((*((WORDREG)targetAddress) & CFI_INTEL_STATUS_BUSY) == 0);
-
- /*
- ** Write the word count - 1.
- */
- *((WORDREG)targetAddress) = (UINT16)(count - 1);
-
- /*
- ** Write the data.
- */
- while (count-- != 0)
- {
- *((WORDREG)targetAddress) = CFISetEndian((UINT16)((sourceData[i]<<8) | sourceData[i+1]));
- targetAddress++;
- i += 2;
- }
-
- /*
- ** Issue the write confirm command.
- */
- *((WORDREG)sectorAddress) = CFI_INTEL_WRITE_CONFIRM;
- }
-
- /*
- ** Poll for completion of the write.
- */
- while (CFIIntelBusy(this));
-
- /*
- ** Test for an error.
- */
- if (*((WORDREG)this->baseAddress) != 0x80)
- {
- /*
- ** An error occurred. Clear the status register, put
- ** the device back into read mode and return.
- */
- *((WORDREG)this->baseAddress) = CFI_INTEL_CLEAR_STATUS;
- *((WORDREG)this->baseAddress) = CFI_INTEL_RESET_TO_READ;
-
- nret = FAILURE;
- }
- else
- {
- /*
- ** The erase command completed successfully. Put the
- ** device back into read mode and return.
- */
- *((WORDREG)this->baseAddress) = CFI_INTEL_RESET_TO_READ;
-
- nret = SUCCESS;
- }
-
- EXCEndCriticalSection(irqState);
- return nret;
- }
- /****************************************************************************
- ** Function CFIIntelIDCodesEntry(): This function places an Intel compatible
- ** FLASH ROM in the read indentify codes mode,
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- **
- ** Outputs: None
- **
- ** Returns: Nothing.
- ****************************************************************************/
- void CFIIntelIDCodesEntry(T_CFIRomDevice *this)
- {
- ((WORDREG)this->baseAddress)[CFI_IDENTIFIER_CODES_ADDRESS] = CFI_IDENTIFIER_CODES_COMMAND;
- }
- /****************************************************************************
- ** Function CFIIntelProgram(): This function will program the specified area
- ** of an Intel compatible FLASH ROM. This is a blocking function and will not
- ** return control until either the programming is complete or an error occurs.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- ** targetAddress, the start address to program to in the ROM.
- ** sourceData, a pointer to the start of the data to be
- ** programmed.
- ** numBytes, the number of bytes to be programmed.
- **
- ** Outputs: None
- **
- ** Returns: SUCCESS if the programming is successful.
- ** FAILURE if this function is not running in RAM, or the
- ** programming failed. The programming is likely to fail
- ** if an attempt is made to program an area of memory that
- ** has not been erased. Specifically if an attempt is made
- ** to change a 0 to a 1.
- ****************************************************************************/
- INT32 CFIIntelProgram(T_CFIRomDevice *this, UINT16 *targetAddress,
- UINT8 *sourceData, UINT32 numBytes)
- {
- UINT32 count;
- INT32 nret;
- UINT16 tempWord;
- UINT32 irqState;
-
- irqState = EXCStartCriticalSection();
-
- /************************************************************************
- ** Mis-aligned write detection and handling.
- ************************************************************************/
-
- /*
- ** Our FLASH ROM is a 16-bit device, however we may be asked to write an
- ** odd number of bytes, or the target address may not be on a 16-bit
- ** boundary. If this is the case use read/modify/write cycles to
- ** write the misaligned data.
- */
- if (((UINT32)targetAddress & 1) != 0)
- {
- /*
- ** The start address is mis-aligned, write the first
- ** byte to align the start address.
- */
-
- /*
- ** Read and modify the first word.
- */
- targetAddress = (UINT16 *)((UINT32)targetAddress & ~1);
- tempWord = targetAddress[0] & CFISetEndian(0xFF00);
- tempWord |= CFISetEndian(sourceData[0]);
-
- /*
- ** Write the word write command.
- */
- *((WORDREG)targetAddress) = CFI_INTEL_WRITE_WORD;
-
- /*
- ** Write the data
- */
- *((WORDREG)targetAddress) = tempWord;
-
- /*
- ** Poll for completion.
- */
- while (CFIIntelBusy(this));
-
- targetAddress++;
- numBytes--;
- sourceData++;
- }
-
- if ((numBytes & 1) != 0)
- {
- /*
- ** The data length is now mis-aligned, write the last byte
- ** to align to data length.
- */
-
- /*
- ** Put the device back into read mode.
- */
- *((WORDREG)this->baseAddress) = CFI_INTEL_RESET_TO_READ;
-
- tempWord = targetAddress[((numBytes-1) >> 1)] & CFISetEndian(0x00FF);
- tempWord |= CFISetEndian((UINT16)(sourceData[(numBytes-1)] << 8));
-
- /*
- ** Write the word write command.
- */
- ((WORDREG)targetAddress)[((numBytes-1) >> 1)] = CFI_INTEL_WRITE_WORD;
-
- /*
- ** Write the data
- */
- ((WORDREG)targetAddress)[((numBytes-1) >> 1)] = tempWord;
-
- /*
- ** Poll for completion.
- */
- while (CFIIntelBusy(this));
-
- numBytes--;
- }
-
- /************************************************************************
- ** Main programming loop.
- ************************************************************************/
-
- /*
- ** Convert the number of bytes to program to a number of
- ** 16-bit words to program.
- */
- count = numBytes >> 1;
-
- /*
- ** Write the data.
- */
- while (count-- != 0)
- {
- /*
- ** Wait for the device to be ready.
- */
- while (CFIIntelBusy(this));
-
- /*
- ** Write the word write command.
- */
- *((WORDREG)targetAddress) = CFI_INTEL_WRITE_WORD;
-
- /*
- ** Write the data
- */
- *((WORDREG)targetAddress) = CFISetEndian((UINT16)((sourceData[0]<<8) | sourceData[1]));
- targetAddress++;
- sourceData += 2;
- }
-
- /*
- ** Poll for completion of the write.
- */
- while (CFIIntelBusy(this));
-
- /*
- ** Test for an error.
- */
- if (*((WORDREG)this->baseAddress) != 0x80)
- {
- /*
- ** An error occurred. Clear the status register, put
- ** the device back into read mode and return.
- */
- *((WORDREG)this->baseAddress) = CFI_INTEL_CLEAR_STATUS;
- *((WORDREG)this->baseAddress) = CFI_INTEL_RESET_TO_READ;
-
- nret = FAILURE;
- }
- else
- {
- /*
- ** The program command completed successfully. Put the
- ** device back into read mode and return.
- */
- *((WORDREG)this->baseAddress) = CFI_INTEL_RESET_TO_READ;
-
- nret = SUCCESS;
- }
-
- EXCEndCriticalSection(irqState);
- return nret;
- }
- /****************************************************************************
- ** Function CFIIntelReset(): This function resets an Intel compatible FLASH
- ** ROM back to read array mode.
- **
- ** Inputs: this, pointer to a T_CFIROMDevice structure.
- **
- ** Outputs: None
- **
- ** Returns: Nothing.
- ****************************************************************************/
- void CFIIntelReset(T_CFIRomDevice *this)
- {
- *(WORDREG)this->baseAddress = CFI_INTEL_RESET_TO_READ;
- }
- /****************************************************************************
- ** Function CFISetEndian(): This function swaps the byte order of a 16-bit
- ** word only if this image has been compiled for little endian operation.
- ** The reason this function is required is that our ROMs are 16-bit devices,
- ** but yet we program them with byte data. This means that we have endian
- ** issues to deal with. All of the functions in this module assume big endian
- ** rules for converting byte data to half-word data. This function is called
- ** in those cases to make sure that they work for little endian operation.
- **
- ** Big endian vs. Little endian example
- ** Say memory contains for following data in byte order 0xAA, 0xBB, 0xCC, 0xDD.
- ** If you read the lowest address as a half word then for a big endian machine
- ** the result will be 0xAABB and 0xBBAA for a little endian machine. If you
- ** want to perform a read, modify, write cycle to replace 0xBB with 0xEE then
- ** the sequence of operations is different for big and little endian. For big
- ** endian you would perform 'new_data = ((old_data & 0xFF00) | 0xEE);'. For
- ** little endian you would perform 'new_data = ((old_data & 0x00FF) | 0xEE00);'
- **
- ** Inputs: value, the 16-bit word to swap or not.
- **
- ** Outputs: None
- **
- ** Returns: value byte swapped if compiled for little endian, or
- ** unaltered if compiled for big endian.
- ****************************************************************************/
- UINT16 CFISetEndian(UINT16 value)
- {
- /*
- ** ST5105 platform is little endian, and maybe other ST platforms are
- ** little endian also. Please make sure that
- */
-
- #if 1 /* __MIPSEL */
- return((UINT16)((value & 0xFF) << 8) | (UINT16)(value >> 8));
- #else
- return(value);
- #endif
- }