diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Board/Flash/SPI/ICHx/SPIFlash.c | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Board/Flash/SPI/ICHx/SPIFlash.c')
-rw-r--r-- | Board/Flash/SPI/ICHx/SPIFlash.c | 1369 |
1 files changed, 1369 insertions, 0 deletions
diff --git a/Board/Flash/SPI/ICHx/SPIFlash.c b/Board/Flash/SPI/ICHx/SPIFlash.c new file mode 100644 index 0000000..022e2ae --- /dev/null +++ b/Board/Flash/SPI/ICHx/SPIFlash.c @@ -0,0 +1,1369 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Board/Flash/SPI/ICHx/SPIFlash.c 1 11/02/17 1:44a Chienhsieh $ +// +// $Revision: 1 $ +// +// $Date: 11/02/17 1:44a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Board/Flash/SPI/ICHx/SPIFlash.c $ +// +// 1 11/02/17 1:44a Chienhsieh +// [TAG] EIP358409 +// [Category] Improvement +// [Description] [SAx0039][Flash_17/16/14/11/10/09/08/7] SPI security +// [Files] Board\Flash\SPI\ICHx\SPIFlash.c +// +// 19 6/10/13 5:26a Calvinchen +// [TAG] EIPNone +// [Category] Bug Fix +// [Severity] Important +// [Symptom] System hangs in EFI OS if Nvram Garbage collection occurred +// [RootCause] RCBA base don't convert to virtual address causes system +// hangs at checking TOP_SWAP bit. +// [Solution] Need to convert RCBA base. +// [Files] SPIFlash.c +// +// 18 3/08/13 3:37a Calvinchen +// [TAG] EIP110515 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Microchip SST26VF064B & SST26VF064BA 8MB SPI Flash part +// support +// [RootCause] Need "Global Block Protection Unlock" before programming. +// [Solution] Added "Global Block Protection Unlock" before programming. +// [Files] SPIFlash.c +// +// 17 12/11/12 5:54a Calvinchen +// [TAG] EIP108531 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Unable to use AMI Flash Lib inside DXE Core +// [RootCause] Procedure Name duplicated +// [Solution] Rename IoDelay to SpiIoDelay +// [Files] SpiFlash.c +// +// 16 10/31/12 3:08a Calvinchen +// [TAG] EIP104018 +// [Category] Improvement +// [Description] Changes for Top Swap enabled. +// [Files] SpiFlash.c +// +// 15 10/18/12 3:05a Calvinchen +// Added SFDP support for VSCC. +// +// 14 9/25/12 12:10a Calvinchen +// [TAG] EIP97017 +// [Category] Improvement +// [Description] 1. MahoBay Flash error fail save +// 2. Keep Quad Enable bit (Bit6) of Status Register for MXIC flash. +// [Files] SPIFlash.c +// +// 13 1/12/12 1:08a Calvinchen +// [TAG] EIP80707 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Flash Error +// [RootCause] Coding Mistake. +// [Solution] Fix coding mistake. +// [Files] SPIFlash.c +// +// 12 2/10/11 3:27a Calvinchen +// Bug Fixed : (EIP#53185)Reading 64 Bytes failed if cross over 4K +// boundary. +// Description : This is supposed to be an ICH/PCH limitation. +// +// 11 10/25/10 9:41a Calvinchen +// Very Slow SPI Read Byte Access. +// +// 10 10/25/10 6:22a Calvinchen +// (EIP45843)Very Slow SPI Read Byte Access. +// +// 9 9/14/10 3:25a Calvinchen +// Added the "SPI_INITIALIAL_WITH_VSCC" token for VSCC register +// initialize. +// +// 8 5/21/10 2:14a Calvinchen +// Bug fixed: Build failed with "undeclared identifier". +// +// 7 3/11/10 6:41a Calvinchen +// Improvement : Added SST AAIWordProgram SPI command to speed up the +// programming time with Intel chipset. +// +// 6 6/24/09 3:25a Calvinchen +// (EIP22177) Updated for Aptio Source Enhancement. +// +// 5 4/27/09 3:30a Calvinchen +// 2.(EIP20459) Added Multiple SPI CSP component support. +// +// 4 12/03/08 1:00a Calvinchen +// (EIP17945)Bug Fixed : Fail to unlock the BIOS region of Flash +// Descriptor. +// +// 3 8/26/08 3:02a Calvinchen +// 1.Fixed Fail to un-protect ATMEL flash. +// 2.Fixed Building failed if ICH_FDOC/FDOD not defined. +// 3.Increase the Timeout counter for waiting the ICH SPI cycle done. +// +// 2 6/26/08 6:56a Calvinchen +// Generic bug fixed. +// +// 1 3/13/08 6:37a Calvinchen +// Added support for Intel ICHx SPI. +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: FlashWrite.c +// +// Description: Flash update routines +// +//<AMI_FHDR_END> +//********************************************************************** +//---------------------------------------------------------------------------- +// Includes +#include <efi.h> +#include <AmiDxeLib.h> +#include "FlashPart.h" +#include "SpiFlash.h" +#include "token.h" +//---------------------------------------------------------------------------- +// Local defines for transaction types +// ICH8/9/10 SPI register defines. +#define SPI_STS 0x90 // SPI Status +#define SPI_CTL 0x91 // SPI Control +#define SPI_ADR 0x08 // SPI Address +#define SPI_DAT0 0x10 // SPI Data 0 +#define SPI_PREOP 0x94 // Prefix Opcode Configuration +#define SPI_OPTYPE 0x96 // Opcode Type Configuration +#define SPI_OPMENU 0x98 // Opcode Menu Configuration +#define RCRB_MMIO_BUC 0x3414 // Backed Up Control Register +// SPI default opcode slots +#define SPI_OPCODE_WRITE_INDEX 0x0 +#define SPI_OPCODE_READ_INDEX 0x1 +#define SPI_OPCODE_ERASE_INDEX 0x2 +#define SPI_OPCODE_READ_S_INDEX 0x3 +#define SPI_OPCODE_READ_ID_INDEX 0x4 +#define SPI_OPCODE_WRITE_S_INDEX 0x5 +#define SPI_OPCODE_WRITE_S_E_INDEX 0x6 +#define SPI_OPCODE_WRITE_E_INDEX 0x7 +#define SPI_OPCODE_AAI_INDEX 0x6 +#define SPI_OPCODE_WRITE_D_INDEX 0x7 +#define SPI_PREFIX_WRITE_S_EN 0x1 +#define SPI_PREFIX_WRITE_EN 0x0 +#define SPI_MAX_DATA_TRANSFER 0x40 +#define ICHX_FDOC 0xb0 // Flash Descriptor Observability Control Register +#define ICHX_FDOD 0xb4 // Flash Descriptor Observability Data Register +#define FLASH_VALID_SIGNATURE 0x0ff0a55a +#define NO_ADDRESS_UPDATE 0 +#ifndef SPI_OPCODE_TYPE_READ_NO_ADDRESS +#define SPI_OPCODE_TYPE_READ_NO_ADDRESS 0x0 +#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS 0x1 +#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS 0x2 +#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS 0x3 +#endif +#define SPI_FLASH_DEVICE_BASE_ADDRESS (0xFFFFFFFF-FLASH_SIZE+1) // [ EIP358409 ] +//---------------------------------------------------------------------------- +// Module level global data +extern UINT16 gFlashId; +extern FLASH_PART *FlashAPI; +//---------------------------------------------------------------------------- +// Function Externs +extern +VOID +SpiChipsetVirtualFixup ( + IN EFI_RUNTIME_SERVICES *pRS +); +//---------------------------------------------------------------------------- +// Local prototypes +VOID +CommonSpiEraseCommand ( + volatile UINT8 *pBlockAddress +); +VOID +CommonSpiProgramCommand ( + volatile UINT8 *pByteAddress, + UINT8 *Byte, + UINT32 *Length +); +VOID +CommonSpiReadCommand ( + volatile UINT8 *pByteAddress, + UINT8 *Byte, + UINT32 *Length +); +BOOLEAN +CommonSpiIsEraseCompleted ( + volatile UINT8 *pBlockAddress, + BOOLEAN *pError, + UINTN *pStatus +); +BOOLEAN +CommonSpiIsProgramCompleted ( + volatile UINT8 *pByteAddress, + UINT8 *Byte, + UINT32 Length, + BOOLEAN *pError, + UINTN *pStatus +); +VOID +CommonSpiBlockWriteEnable ( + volatile UINT8 *pBlockAddress +); +VOID +CommonSpiBlockWriteDisable ( + volatile UINT8 *pBlockAddress +); +VOID +CommonSpiDeviceWriteEnable ( + VOID +); +VOID +CommonSpiDeviceWriteDisable ( + VOID +); +VOID +CommonSpiDeviceVirtualFixup ( + EFI_RUNTIME_SERVICES *pRS +); +// [ EIP358409 ]+>>> +VOID +SpiBlockProtectUpdate ( + IN volatile UINT8 *pBlockAddress, + IN UINT8 bStatusData +); +// [ EIP358409 ]+<<< +//---------------------------------------------------------------------------- +// Local Variables +FLASH_PART mCommonSpiFlash ={ + CommonSpiReadCommand, + CommonSpiEraseCommand, + CommonSpiProgramCommand, + CommonSpiIsEraseCompleted, + CommonSpiIsProgramCompleted, + CommonSpiBlockWriteEnable, + CommonSpiBlockWriteDisable, + CommonSpiDeviceWriteEnable, + CommonSpiDeviceWriteDisable, + CommonSpiDeviceVirtualFixup, + 1, // default value, should be changed in Init function + SECTOR_SIZE_4KB +}; +EX_FLASH_PART mExFlashPart = { + {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},0,0}, + FLASH_SIZE, // flash size, should be changed in Init function + 0, // flash part id, should be changed in Init function + 0 // flash part string, should be changed in + // Init function +}; +volatile UINT8 *gSPIBASE = (UINT8*)(UINTN)(SB_RCBA + SPI_BASE_ADDRESS); +volatile UINT8 *gRCBABASE = (UINT8*)(UINTN)SB_RCBA; +UINT8 gbDeviceVirtual = 0; +UINT8 gbDeviceWriteEnabled = 0; +//---------------------------------------------------------------------------- +// Function Definitions + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SpiIoDelay +// +// Description: +// +// Input: +// +// Output: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +SpiIoDelay (VOID) +{ + UINT8 bTimeout; + for ( bTimeout = 0; bTimeout < 33; bTimeout++ ) { + IoWrite8( 0xEB, 0x55 ); + IoWrite8( 0xEB, 0xAA ); + } + return ; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: WaitForSpiCycleDone +// +// Description: +// +// Input: +// +// Output: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +WaitForSpiCycleDone (VOID) +{ + UINT32 dTimeout; + UINT8 bCyclyDone; + + for ( dTimeout = 0, bCyclyDone = 0; dTimeout < 0x4000000; dTimeout++ ) { + bCyclyDone = *(volatile UINT8*)( gSPIBASE + SPI_STS ); + if ( bCyclyDone & BIT02 ) break; + } + // write BIT2 to clear CycleDone status + *(volatile UINT8*)( gSPIBASE + SPI_STS ) = BIT02; + +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SpiWriteDisable +// +// Description: This procedure issuess SPI Write Disable if AAIWordProgram. +// +// Input: None. +// +// Output: None. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID SpiWriteDisable (VOID) +{ + // Opcode menu slot 7 is configured as "Write Disable" if AAIWordProgram. + *(volatile UINT16*)(gSPIBASE + SPI_CTL) = \ + ( SPI_OPCODE_WRITE_D_INDEX << 4) + BIT01; + // wait for chipset SPI cycle completed. + WaitForSpiCycleDone(); + return ; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CheckAaiWordProram +// +// Description: This procedure checks whether issues the AAIWordProgram command. +// +// Input: dAddr - Start address to be written. +// dLength - Number of bytes to be written. +// +// Output: TRUE - Yes +// FALSE - No +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN +CheckAaiWordProram ( + IN UINT32 dAddr, + IN UINT32 dLength +) +{ + if ((mExFlashPart.AAIWordProgram != 0) && !(dAddr & 1) && (dLength >= 2)) + return TRUE; + return FALSE; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CommonSpiReadStatus +// +// Description: +// +// Input: None. +// +// Output: Status Register which is read from SPI flash. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8 +CommonSpiReadStatus ( + IN UINT32 dUpdateAddr +) +{ + UINT16 wSpiCmd; + + if( dUpdateAddr ) *(volatile UINT32*)( gSPIBASE + SPI_ADR ) = dUpdateAddr; + // Opcode menu slot 3 is configured as "Read Status Register" + wSpiCmd = SPI_OPCODE_READ_S_INDEX << 4; + // indicate that data phase is required + wSpiCmd += (1 << 14); + // Set BIT1 (Go) + *(volatile UINT16*)( gSPIBASE + SPI_CTL ) = wSpiCmd + BIT01; + // wait for spi cycle completed. + WaitForSpiCycleDone(); + // return status register. + return ( *(volatile UINT8*)( gSPIBASE + SPI_DAT0 ) ); +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: WaitForWriteOperationCompleted +// +// Description: +// +// Input: None. +// +// Output: None. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +WaitForWriteOperationCompleted (VOID) +{ + UINT16 wWaitStsRetry; + UINT8 bStatus; + + for( wWaitStsRetry = 0; wWaitStsRetry < 0xFFFF; wWaitStsRetry++ ) { + // read flash status register. + bStatus = CommonSpiReadStatus( NO_ADDRESS_UPDATE ); + // Is operation busy ? + if( !( bStatus & 0x1 ) ) break; + } +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CommonSpiWriteStatus +// +// Description: Routine for Write SPI Status Register. +// +// Input: None. +// +// Output: Status Register which is read from SPI flash. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +CommonSpiWriteStatus ( + IN UINT8 bWriteData, + IN UINT8 bOpcodeIndex, + IN UINT8 bIsDataPhase, + IN UINT8 bPrefixOp, + IN UINT32 dSectorAddress +) +{ + UINT16 wSpiCmd; + + *(volatile UINT8*)( gSPIBASE + SPI_DAT0 ) = bWriteData; + *(volatile UINT32*)( gSPIBASE + SPI_ADR ) = dSectorAddress; + // Opcode menu slot 3 is configured as "Read Status Register" + wSpiCmd = bOpcodeIndex << 4; + // indicate that data phase is required + wSpiCmd += ( bIsDataPhase << 14 ); + // BIT3(Preop 1) + wSpiCmd += ( bPrefixOp << 3 ); + // Set BIT1 (Go), BIT2(Atomic w/ Prefix), + *(volatile UINT16*)( gSPIBASE + SPI_CTL ) = wSpiCmd + BIT01 + BIT02; + // wait for spi cycle completed. + WaitForSpiCycleDone(); + // wait for SPI flash operation completed. + WaitForWriteOperationCompleted(); + // return status register. + return ; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CommonSpiReadByte +// +// Description: +// +// Input: dByteAddress Address that need to be read. +// +// Output: BYTE Value which is read from SPI flash. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT8 +CommonSpiReadByte ( + IN UINT32 dByteAddress +) +{ + UINT8 bData; + UINT32 dLength = sizeof(UINT8); + CommonSpiReadCommand((volatile UINT8*)dByteAddress, &bData, &dLength); + return bData; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CommonConvertSpiAddress +// +// Description: +// +// Input: +// +// Output: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +CommonConvertSpiAddress ( + IN volatile UINT8 *pAddress, + OUT UINT32 *pdCnvtAddress +) +{ + UINT32 dIchSpiFDOD; + static UINT32 gBiosRegionBase = 0, gBiosRegionLimit = 0; + + // if flash identified, here checks the BIOS region of Flash + // Descriptor Table. + if ( mExFlashPart.FlashVenDevId ) { + if ( !gBiosRegionBase ) { + *(volatile UINT32*)( gSPIBASE + ICHX_FDOC ) = 0; + dIchSpiFDOD = *(volatile UINT32*)( gSPIBASE + ICHX_FDOD ); + if ( dIchSpiFDOD == FLASH_VALID_SIGNATURE ) { + *(volatile UINT32*)( gSPIBASE + ICHX_FDOC ) = ( BIT13 + BIT02 ); + do { + dIchSpiFDOD = *(volatile UINT32*)( gSPIBASE + ICHX_FDOD ); + } while( dIchSpiFDOD == FLASH_VALID_SIGNATURE ); + gBiosRegionBase = ( ( (dIchSpiFDOD >> 16) + 1 ) << 12 ); + gBiosRegionLimit = ((dIchSpiFDOD >> 4) | 0xfff) + 1; + } + else { + gBiosRegionBase = mExFlashPart.FlashCapacity; + gBiosRegionLimit = mExFlashPart.FlashCapacity; + } + } + } + if ( gbDeviceVirtual ) { + // pAddress - offset from Flash Device Base. + pAddress -= FlashDeviceBase; + // pAddress - 32bit memory mapping address. + pAddress += (0xFFFFFFFF - FLASH_SIZE) + 1; + } + // pAddress - physical address in flash. + pAddress += gBiosRegionBase; + if ((UINT32)pAddress >= gBiosRegionLimit) return EFI_INVALID_PARAMETER; + *pdCnvtAddress = (UINT32)pAddress; + return EFI_SUCCESS; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: InitializeSpiEnvironment +// +// Description: +// +// Input: +// +// Output: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +InitializeSpiEnvironment ( + IN OUT FLASH_INFO *FlashInfo +) +{ + //Program first DWORD of opcode commands + *((volatile UINT32*)( gSPIBASE + R_RCRB_SPI_OPMENU + 0 )) = (UINT32) + // Write Byte + ( (FlashInfo->Write.Opcode << (SPI_OPCODE_WRITE_INDEX * 8)) | \ + // Read Data + (FlashInfo->Read.Opcode << (SPI_OPCODE_READ_INDEX * 8)) | \ + // Erase 64k Sector + (FlashInfo->Erase.Opcode << (SPI_OPCODE_ERASE_INDEX * 8)) | \ + // Read Device Status Reg + (FlashInfo->ReadStatus.Opcode << (SPI_OPCODE_READ_S_INDEX * 8)) ); + + //Program second DWORD of Opcode commands + *((volatile UINT32*)( gSPIBASE + R_RCRB_SPI_OPMENU + 4 )) = (UINT32) + // Read device ID + ((FlashInfo->ReadId.Opcode << ((SPI_OPCODE_READ_ID_INDEX - 4) * 8)) | \ + // Write Status Register + (FlashInfo->WriteStatus.Opcode << \ + ((SPI_OPCODE_WRITE_S_INDEX - 4) * 8)) | \ + // Write Status Enable Register + (FlashInfo->WriteStatusEnable.Opcode << \ + ((SPI_OPCODE_WRITE_S_E_INDEX - 4) * 8))); + + //Program opcode types + *((volatile UINT16*)( gSPIBASE + R_RCRB_SPI_OPTYPE )) = (UINT16) + // write with address. + (FlashInfo->Write.OpcodeType << (SPI_OPCODE_WRITE_INDEX * 2) | \ + // read with address. + FlashInfo->Read.OpcodeType << (SPI_OPCODE_READ_INDEX * 2) | \ + // write with address. + FlashInfo->Erase.OpcodeType << (SPI_OPCODE_ERASE_INDEX * 2) | \ + // read w/o no adress. + FlashInfo->ReadStatus.OpcodeType << (SPI_OPCODE_READ_S_INDEX * 2) | \ + // read with address. + FlashInfo->ReadId.OpcodeType << (SPI_OPCODE_READ_ID_INDEX * 2) | \ + // write w/o address. + FlashInfo->WriteStatus.OpcodeType << (SPI_OPCODE_WRITE_S_INDEX * 2) | \ + // write w/o address. + FlashInfo->WriteStatusEnable.OpcodeType << \ + (SPI_OPCODE_WRITE_S_E_INDEX * 2)); + + //set up the prefix opcodes for commands + *((volatile UINT16*)( gSPIBASE + R_RCRB_SPI_PREOP )) = (UINT16) + ( ( FlashInfo->WriteStatusEnable.Opcode << 8 ) | \ + ( FlashInfo->WriteEnable.Opcode ) ); + + //set up Program Opcode and Optype if AAIWordProgram. + if (mExFlashPart.AAIWordProgram != 0) { + UINT8 bOpType = 0; + *((volatile UINT16*)(gSPIBASE + R_RCRB_SPI_OPMENU + 6)) = 0x4ad; + bOpType = *((volatile UINT8*)(gSPIBASE + R_RCRB_SPI_OPTYPE + 1)); + bOpType = ((bOpType & 0xf) | \ + (SPI_OPCODE_TYPE_WRITE_NO_ADDRESS << 6) | \ + (SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS << 4)); + *((volatile UINT8*)(gSPIBASE + R_RCRB_SPI_OPTYPE + 1)) = bOpType; + } + return ; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: SerialFlashDiscoveryForQuadRead +// +// Description: This procedure checks SPI Quad Read support through SFDP. +// +// Input: None. +// +// Output: EFI_STATUS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +SerialFlashDiscoveryForQuadRead (VOID) +{ +#if defined SPI_INITIALIZE_WITH_VSCC && SPI_INITIALIZE_WITH_VSCC == 1 + UINT8 SfdpData[256]; + UINT16 wSpiCmd, wOffset, j; + UINT32 Index; + // Serial Flash Discoverable Parameters Command "0x5A". + *(volatile UINT8*)(gSPIBASE + SPI_OPMENU + 7) = 0x5a; + // Do nothing if SPI Registers is locked. + if (*(volatile UINT8*)(gSPIBASE + SPI_OPMENU + 7) != 0x5a) + return EFI_WRITE_PROTECTED; + // Update SPI OpMenu[7] to "READ WITH ADDRESS". + SfdpData[0] = *(volatile UINT8*)(gSPIBASE + SPI_OPTYPE + 1); + *(volatile UINT8*)(gSPIBASE + SPI_OPTYPE + 1) = (SfdpData[0] & 0x3f) | 0x80; + MemSet(SfdpData, 256, 0); + for (Index = 0; Index < 256; Index += 64) { + // Set SPI read-address = 0, 64, 128, 256 + *(volatile UINT32*)(gSPIBASE + SPI_ADR) = Index; + // set opcode for "5A" + wSpiCmd = SPI_OPCODE_WRITE_E_INDEX << 4; + // set transaction = 64 bytes + wSpiCmd += ((64 - 1) << 8); + // indicate that data phase is required + wSpiCmd += (1 << 14); + // Go (BIT1) + *(volatile UINT16*)(gSPIBASE + SPI_CTL) = wSpiCmd + BIT01; + WaitForSpiCycleDone(); + for (j = 0; j < 64; j++) + *(SfdpData + Index + j) = *(volatile UINT8*)(gSPIBASE + SPI_DAT0 + j); + // Serial Flash Discoverable Parameters (SFDP) Signature = 50444653h + if (Index == 0) { + wOffset = 0; + if (*(UINT32*)&SfdpData[wOffset] != 0x50444653) { + if (*(UINT32*)&SfdpData[++wOffset] != 0x50444653) + return EFI_UNSUPPORTED; + } + } + } + // SFDP opode at address Ch bits 23:00 = Parameter ID 0 table Address + Index = (*(UINT32*)&SfdpData[wOffset + 0xC] & 0x00FFFFFF); + // SFDP opode at address 05h(SFPD Major Revisions) must = 0001h + // SFDP opode at address 0Ah(Serial Flash Basic Major Revisions) must = 0001h + if ((SfdpData[wOffset + 5] != 0x1) || (SfdpData[wOffset + 0xA] != 0x1) || \ + ((Index + 0x10) > 256)) return EFI_UNSUPPORTED; + // Parameter ID 0 Table BIT[21] - Fast Read Quad I/O. + // Parameter ID 0 Table BIT[22] - Fast Read Quad Output. + if (*(UINT32*)&SfdpData[Index + 1] & (BIT21 + BIT22)) return EFI_SUCCESS; +#endif + return EFI_UNSUPPORTED; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: GlobalBlockProtectionUnlock +// +// Description: This procedure unlocks "Global Block Protection" for Microchip +// 26VF series flash parts. +// +// Input: None +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +GlobalBlockProtectionUnlock (VOID) +{ + UINT8 SavedOpType; + + if (mExFlashPart.GlobalBlockUnlock != TRUE) return; + // Serial Flash Discoverable Parameters Command "0x5A". + *(volatile UINT8*)(gSPIBASE + SPI_OPMENU + 7) = 0x98; + // Do nothing if SPI Registers is locked. + if (*(volatile UINT8*)(gSPIBASE + SPI_OPMENU + 7) != 0x98) return; + // Update SPI OpMenu[7] to "WRITE W/O ADDRESS". + SavedOpType = *(volatile UINT8*)(gSPIBASE + SPI_OPTYPE + 1); + *(volatile UINT8*)(gSPIBASE + SPI_OPTYPE + 1) = (SavedOpType & 0x3f) | BIT06; + // Opcode menu slot 7 is configured as "Write Disable" if AAIWordProgram. + *(volatile UINT16*)(gSPIBASE + SPI_CTL) = \ + (SPI_OPCODE_WRITE_D_INDEX << 4) + BIT01; + // wait for chipset SPI cycle completed. + WaitForSpiCycleDone(); + return ; +} +// [ EIP358409 ]+>>> +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: RemoveWriteStatusOpcode +// +// Description: +// +// Input: +// +// Output: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +RemoveWriteStatusOpcode ( + IN OUT FLASH_INFO *FlashInfo +) +{ + + FlashInfo->WriteStatus.Opcode = FlashInfo->ReadId.Opcode; + FlashInfo->WriteStatus.OpcodeType = FlashInfo->ReadId.OpcodeType; + + //Program second DWORD of Opcode commands + *((volatile UINT32*)( gSPIBASE + R_RCRB_SPI_OPMENU + 4 )) = (UINT32) + // Read device ID + ((FlashInfo->ReadId.Opcode << ((SPI_OPCODE_READ_ID_INDEX - 4) * 8)) | \ + // Write Status Register + (FlashInfo->WriteStatus.Opcode << \ + ((SPI_OPCODE_WRITE_S_INDEX - 4) * 8)) | \ + // Write Status Enable Register + (FlashInfo->WriteStatusEnable.Opcode << \ + ((SPI_OPCODE_WRITE_S_E_INDEX - 4) * 8))); + + //Program opcode types + *((volatile UINT16*)( gSPIBASE + R_RCRB_SPI_OPTYPE )) = (UINT16) + // write with address. + (FlashInfo->Write.OpcodeType << (SPI_OPCODE_WRITE_INDEX * 2) | \ + // read with address. + FlashInfo->Read.OpcodeType << (SPI_OPCODE_READ_INDEX * 2) | \ + // write with address. + FlashInfo->Erase.OpcodeType << (SPI_OPCODE_ERASE_INDEX * 2) | \ + // read w/o no adress. + FlashInfo->ReadStatus.OpcodeType << (SPI_OPCODE_READ_S_INDEX * 2) | \ + // read with address. + FlashInfo->ReadId.OpcodeType << (SPI_OPCODE_READ_ID_INDEX * 2) | \ + // write w/o address. + FlashInfo->WriteStatus.OpcodeType << (SPI_OPCODE_WRITE_S_INDEX * 2) | \ + // write w/o address. + FlashInfo->WriteStatusEnable.OpcodeType << \ + (SPI_OPCODE_WRITE_S_E_INDEX * 2)); + + + return ; +} +// [ EIP358409 ]+<<< +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: ReinitializeSpiEnvironment +// +// Description: +// +// Input: +// +// Output: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +ReinitializeSpiEnvironment ( + IN OUT FLASH_INFO *FlashInfo +) +{ + UINT8 *BlockAddress; // [ EIP358409 ] +#if defined SPI_INITIALIZE_WITH_VSCC && SPI_INITIALIZE_WITH_VSCC == 1 + // Program UPPER/LOWER VSCC register. + UINT32 dVSCC = 0; + EFI_STATUS Status; + // Erase Opcode. + dVSCC = FlashInfo->Erase.Opcode << 8; + // Block/Sector Erase Size. + if (FlashInfo->SectorSize == SECTOR_SIZE_4KB) dVSCC |= BIT00; + else if (FlashInfo->SectorSize == SECTOR_SIZE_8KB) dVSCC |= BIT01; + else if (FlashInfo->SectorSize == SECTOR_SIZE_64KB) dVSCC |= (BIT00 + BIT01); + // Write Granularity. + if (FlashInfo->PageSize != 1) dVSCC |= BIT02; + // Write Status Required. + if (FlashInfo->WriteStatusEnable.Opcode == 0x50) dVSCC |= BIT03; + // Write Enable On Write Status. + if (FlashInfo->WriteStatusEnable.Opcode == 0x39) dVSCC |= BIT04; + Status = SerialFlashDiscoveryForQuadRead(); + if (!EFI_ERROR(Status)) { + switch ((UINT8)mExFlashPart.FlashVenDevId) { + case 0xEF : // Winbond + case 0x37 : // AMIC + case 0x01 : // Spansion + dVSCC |= BIT5; break; + case 0xC2 : // MXIC + dVSCC |= BIT6; break; + case 0x1F : // Atmel + dVSCC |= (BIT5 + BIT6); break; + case 0xBF : // SST/Microchip + dVSCC |= BIT7; break; + break; + default : break; + } + } + if (Status != EFI_WRITE_PROTECTED) { +#if LOWER_VSCC_REG != 0 + *(volatile UINT32*)(gSPIBASE + LOWER_VSCC_REG) = dVSCC; +#endif +#if UPPER_VSCC_REG != 0 + *(volatile UINT32*)(gSPIBASE + UPPER_VSCC_REG) = dVSCC; +#endif + } +#endif + GlobalBlockProtectionUnlock(); + InitializeSpiEnvironment ( FlashInfo ); +// [ EIP358409 ]+>>> + BlockAddress = (UINT8*)SPI_FLASH_DEVICE_BASE_ADDRESS; + SpiBlockProtectUpdate (BlockAddress, 0); + RemoveWriteStatusOpcode(FlashInfo); +// [ EIP358409 ]+<<< +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: CommonSpiReadId +// +// Description: +// +// Input: +// +// Output: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN +CommonSpiReadId ( + IN FLASH_INFO *FlashInfo, + IN OUT UINT32 *dFlashId +) +{ + UINT16 wSpiCmd = 0xFFFF; + + InitializeSpiEnvironment( FlashInfo ); + // Set SPI read-address = 0 + *(volatile UINT32*)( gSPIBASE + SPI_ADR ) = 0; + // set opcode for "Read ID" + wSpiCmd = SPI_OPCODE_READ_ID_INDEX << 4; + // set transaction = 3 bytes + wSpiCmd += ( ( 3 - 1 ) << 8 ); + // indicate that data phase is required + wSpiCmd += ( 1 << 14 ); + // Go (BIT1) + *(volatile UINT16*)( gSPIBASE + SPI_CTL ) = wSpiCmd + BIT01; + WaitForSpiCycleDone(); + SpiIoDelay(); + *dFlashId = *(volatile UINT32*)( gSPIBASE + SPI_DAT0 ) & 0x00FFFFFF; + return TRUE; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiEraseCommand +// +// Description: This API function erases a block in the flash. Flash model +// specific code will branch out from this routine +// +// Input: pBlockAddress Block that need to be erased +// +// Output: Nothing +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +CommonSpiEraseCommand ( + IN volatile UINT8* pBlockAddress +) +{ + volatile UINT32 dSectorAddr; + UINT32 dNByte, dPhyAddress; + UINT16 wEraseRetry, wNumSectors, wSector; + UINT16 wSpiCmd; + + // These parts only erase in 64K sectors + InitializeSpiEnvironment( &mExFlashPart.FlashCommandMenu ); + wNumSectors = ( FlashBlockSize / FlashAPI->FlashSectorSize ); + for ( wSector = 0; wSector < wNumSectors ; wSector++ ) { + dSectorAddr = (UINT32)(pBlockAddress + \ + (wSector * FlashAPI->FlashSectorSize)); + if (EFI_ERROR(CommonConvertSpiAddress( \ + (volatile UINT8*)dSectorAddr, &dPhyAddress))) return; + for ( dNByte = 0; dNByte < FlashAPI->FlashSectorSize; dNByte++ ) { + if (0xFF != CommonSpiReadByte(dSectorAddr + dNByte)) break; + } + if ( dNByte == FlashAPI->FlashSectorSize ) continue; + for ( wEraseRetry = 0; wEraseRetry < FLASH_RETRIES; wEraseRetry++ ) { + *(volatile UINT32*)( gSPIBASE + SPI_ADR ) = dPhyAddress; + // opcode index 2 is programmed for erase command. + // Set BIT1 (Go), BIT2(Atomic w/ Prefix) + wSpiCmd = ( SPI_OPCODE_ERASE_INDEX << 4) + BIT01 + BIT02; + *(volatile UINT16*)( gSPIBASE + SPI_CTL ) = wSpiCmd; + // wait for chipset SPI cycle completed. + WaitForSpiCycleDone(); + // wait for SPI flash operation completed. + WaitForWriteOperationCompleted(); + // write operation appeared to succeed, now read back byte + // and compare. + if (CommonSpiReadByte(dSectorAddr) == 0xFF) break; + } + } +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiProgramCommand +// +// Description: This function programs a byte data to the specified location +// +// Input: *pByteAddress Location where the data to be written +// Bytes - data to be written. +// Length - number of bytes to write +// +// Output: Length - number of bytes that were not written +// +// Return: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +CommonSpiProgramCommand ( + IN volatile UINT8 *pByteAddress, + IN UINT8 *Byte, + IN OUT UINT32 *Length +) +{ + UINT8 bFlashRetry = 0; + UINT16 wProgBytes = 0, wNumBytes = 0; + UINT16 wSpiCmd = 0, wRetry = 0, wMaxNumBytes = 0; + UINT32 dPhyAddress = 0; + + + InitializeSpiEnvironment( &mExFlashPart.FlashCommandMenu ); + wProgBytes = mCommonSpiFlash.FlashProgramSize; + if ( mCommonSpiFlash.FlashProgramSize != 1 ) { + // Limit the max transfer to the number of bytes the chipset can + // transfer per cycle + if ( *Length >= SPI_MAX_DATA_TRANSFER ) + wProgBytes = SPI_MAX_DATA_TRANSFER; + else wProgBytes = *Length; + // this is currently for the WINBOND parts only + // mask off lowest 8 bits of address so that we can determine how + // many bytes we can write before we hit the end of a page + wMaxNumBytes = 0x100 - ((UINT32)pByteAddress & 0xFF); + if ( (UINT32)pByteAddress & 0x1 ) wProgBytes = 1; + else if ( wProgBytes > wMaxNumBytes ) wProgBytes = wMaxNumBytes; + } else if(CheckAaiWordProram((UINT32)pByteAddress, *Length)) wProgBytes = 2; + for ( bFlashRetry = 0; bFlashRetry < FLASH_RETRIES; bFlashRetry++ ) { + // check if do the data need to be programmed ? + for ( wNumBytes = 0; wNumBytes < wProgBytes; wNumBytes++ ) { + if ( *( Byte + wNumBytes ) != 0xFF ) break; + } + // The data is empty and don't need to be programmed. + if ( wNumBytes == wProgBytes ) break; + // update data to chipset SPI data transfer registers. + for ( wNumBytes = 0; wNumBytes < wProgBytes; wNumBytes++ ) { + for ( wRetry = 0; wRetry < 0x400; wRetry ++ ) { + *(volatile UINT8*)( gSPIBASE + SPI_DAT0 + wNumBytes ) = \ + *( Byte + wNumBytes ); + // verified for checking the data is correct. + if ( *( Byte + wNumBytes ) == \ + *(volatile UINT8*)( gSPIBASE + SPI_DAT0 + wNumBytes ) ) + break; + } + } + if (EFI_ERROR(CommonConvertSpiAddress( \ + (volatile UINT8*)pByteAddress, &dPhyAddress))) return; + *(volatile UINT32*)( gSPIBASE + SPI_ADR ) = dPhyAddress; + // BIT14 - indicate that it's data cycle. + wSpiCmd = ( 1 << 14 ); + // BIT[8..13] - update the number of bytes to be written. + wSpiCmd += ( wProgBytes - 1 ) << 8; + // opcode index 0 is programmed for program command. + // Set BIT1 (Go), BIT2(Atomic w/ Prefix) + if (CheckAaiWordProram(dPhyAddress, wProgBytes)) + wSpiCmd += ( SPI_OPCODE_AAI_INDEX << 4) + BIT01 + BIT02; + else wSpiCmd += ( SPI_OPCODE_WRITE_INDEX << 4) + BIT01 + BIT02; + *(volatile UINT16*)( gSPIBASE + SPI_CTL ) = wSpiCmd; + // wait for chipset SPI cycle completed. + WaitForSpiCycleDone(); + // wait for chipset SPI flash operation completed. + WaitForWriteOperationCompleted(); + // Issue SPI Write Disable if SST AAIWordProgram supported. + if (CheckAaiWordProram(dPhyAddress, wProgBytes)) SpiWriteDisable(); + // write operation appeared to succeed, now read back byte and compare + // set control for 1-byte data read, no prefix + for ( wNumBytes = 0; wNumBytes < wProgBytes; wNumBytes++ ) { + if (*(Byte + wNumBytes) != \ + CommonSpiReadByte((UINT32)(pByteAddress + wNumBytes))) break; + } + if ( wNumBytes == wProgBytes ) break; + } + // Don't forget to return the number of bytes not written + *Length = *Length - (UINT32)wProgBytes; + return; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiReadCommand +// +// Description: This function programs a byte data to the specified location +// +// Input: *pByteAddress Location where the data to be written +// Bytes - data to be written. +// Length - number of bytes to write +// +// Output: Length - number of bytes that were not written +// +// Return: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CommonSpiReadCommand ( + IN volatile UINT8 *pByteAddress, + OUT UINT8 *Byte, + IN OUT UINT32 *Length +) +{ + UINT32 dReadAddress = 0; + UINT16 wSpiCmd, i, wMaxRead = 0; + + InitializeSpiEnvironment( &mExFlashPart.FlashCommandMenu ); + if (EFI_ERROR(CommonConvertSpiAddress( \ + (volatile UINT8*)pByteAddress, &dReadAddress))) return; + wMaxRead = 0x100 - (dReadAddress & 0xff); + if (wMaxRead > SPI_MAX_DATA_TRANSFER) wMaxRead = SPI_MAX_DATA_TRANSFER; + if (wMaxRead > *Length) wMaxRead = (UINT16)*Length; + // update the read address. + *(volatile UINT32*)( gSPIBASE + SPI_ADR ) = dReadAddress; + // Opcode menu slot 1 is configured as "Read Flash" + wSpiCmd = ( SPI_OPCODE_READ_INDEX << 4 ) + BIT01; + // indicate that data phase is required + wSpiCmd += (1 << 14); + // BIT[8..13] - update the number of bytes to be read. + wSpiCmd += (wMaxRead - 1) << 8; + *(volatile UINT16*)( gSPIBASE + SPI_CTL ) = wSpiCmd; + // wait for spi cycle completed. + WaitForSpiCycleDone(); + // read data + for (i = 0; i < wMaxRead; i++) + *(Byte + i) = *(volatile UINT8*)(gSPIBASE + SPI_DAT0 + i); + *Length = *Length - (UINT32)wMaxRead; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiIsEraseCompleted +// +// Description: This function verifies whether the block erase +// command is completed and returns the status of the command +// +// Input: *pBlockAddress Location of the block erase +// +// Output: *pError True on error and false on success +// *Status Error status code (0 - Success) +// +// Return: TRUE If operation completed successfully +// *pError = FALSE, *pStatus = 0 +// FALSE If operation failed +// *pError = TRUE, *pStatus = error status +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN +CommonSpiIsEraseCompleted ( + IN volatile UINT8 *pBlockAddress, + OUT BOOLEAN *pError, + OUT UINTN *pStatus +) +{ + UINT32 dNumBytes; + UINT8 bByte; + + for ( dNumBytes = 0; dNumBytes < FlashBlockSize; dNumBytes++ ) { + // Check for Top Swap enabled + if (*(volatile UINT8*)(gRCBABASE + RCRB_MMIO_BUC) & BIT00) + bByte = CommonSpiReadByte((UINT32)(pBlockAddress + dNumBytes)); + else bByte = *(volatile UINT8*)(pBlockAddress + dNumBytes); + if (bByte != 0xFF) { + if ( pStatus ) *pStatus = EFI_NOT_READY; + if ( pError ) *pError = TRUE; + return FALSE; + } + } + if ( pError ) *pError = FALSE; + if ( pStatus ) *pStatus = EFI_SUCCESS; + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiIsProgramCompleted +// +// Description: This function verifies whether the program (page or byte) +// command is completed and returns the status of the command +// +// Input: *pByteAddress Location of the program command +// Byte Last data byte written +// +// Output: *pError True on error and false on success +// *Status Error status code (0 - Success) +// +// Return: TRUE If operation completed successfully +// *pError = FALSE, *pStatus = 0 +// FALSE If operation failed +// *pError = TRUE, *pStatus = error status +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN +CommonSpiIsProgramCompleted ( + IN volatile UINT8 *pByteAddress, + IN UINT8 *Byte, + IN UINT32 Length, + OUT BOOLEAN *pError, + OUT UINTN *pStatus +) +{ + UINT32 dNumBytes; + UINT8 bByte, bReadByte; + + for ( dNumBytes = 0; dNumBytes < Length; dNumBytes++ ) { + bByte = *(Byte + dNumBytes); + // Check for Top Swap enabled + if (*(volatile UINT8*)(gRCBABASE + RCRB_MMIO_BUC) & BIT00) + bReadByte = CommonSpiReadByte((UINT32)(pByteAddress + dNumBytes)); + else bReadByte = *(volatile UINT8*)(pByteAddress + dNumBytes); + if (bByte != bReadByte) { + if ( pStatus ) *pStatus = EFI_NOT_READY; + if ( pError ) *pError = TRUE; + return FALSE; + } + } + if ( pError ) *pError = FALSE; + if ( pStatus ) *pStatus = EFI_SUCCESS; + return TRUE; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SpiBlockProtectUpdate +// +// Description: This function writes the status register. +// +// Input: *pBlockAddress - Address within the block to write enable. +// bStatusData - Value to be written to Status Register. +// +// Output: None +// +// Return: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +SpiBlockProtectUpdate ( + IN volatile UINT8 *pBlockAddress, + IN UINT8 bStatusData +) +{ + UINT8 bStatusReg = 0, bPrefixOp, bDataPhase = 1, bBPbits; + UINT32 dSectorAddr = 0; + + if (EFI_ERROR(CommonConvertSpiAddress(pBlockAddress, &dSectorAddr))) return; + bStatusReg = CommonSpiReadStatus (dSectorAddr); + bPrefixOp = SPI_PREFIX_WRITE_EN; // Use Prefix 0 w/o address + switch ( (UINT8)mExFlashPart.FlashVenDevId ) { + case 0xBF : + // if SST flash, prefix 1 w/o address + if (mExFlashPart.GlobalBlockUnlock == TRUE) return; + bBPbits = (BIT02 + BIT03 + BIT04 + BIT05); + bPrefixOp = SPI_PREFIX_WRITE_S_EN; + break; + case 0x1F : + // if ATMEL flash, prefix 0 w/ address + bBPbits = (BIT02 + BIT03); + break; + case 0x20 : + // if MXIC flash, keep Quad Enable bit (BIT6) state. + bBPbits = (BIT02 + BIT03 + BIT04 + BIT06); + break; + default : + bBPbits = (BIT02 + BIT03 + BIT04); + } + bStatusReg &= bBPbits; // keep valid bits. + bStatusData &= bBPbits; // keep valid bits. + if (bStatusReg != bStatusData) { + CommonSpiWriteStatus ( bStatusData, \ + SPI_OPCODE_WRITE_S_INDEX, \ + bDataPhase, \ + bPrefixOp, \ + dSectorAddr ); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiBlockWriteEnable +// +// Description: This function contains any flash specific code need to +// enable a particular flash block write +// +// Input: *pBlockAddress - Address within the block to write enable +// +// Output: None +// +// Return: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +CommonSpiBlockWriteEnable ( + IN volatile UINT8 *pBlockAddress +) +{ + SpiBlockProtectUpdate (pBlockAddress, 0); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiBlockWriteDisable +// +// Description: This function contains any flash specific code need to +// disable a particular flash block write +// +// Input: *pBlockAddress - Address within the block to write disable +// +// Output: None +// +// Return: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +CommonSpiBlockWriteDisable ( + IN volatile UINT8 *pBlockAddress +) +{ +#if BLOCK_PROTECT_ENABLE + SpiBlockProtectUpdate (pBlockAddress, 0xff); +#endif +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiDeviceWriteEnable +// +// Description: This function contains any flash specific code need to +// enable flash write +// +// Input: None +// +// Output: None +// +// Return: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +CommonSpiDeviceWriteEnable (VOID) +{ + // check is DeviceWrite enabled, if yes, don't enable it again, + // else, enable it. + if ( !gbDeviceWriteEnabled ) { + gbDeviceWriteEnabled = 1; + } +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiDeviceWriteDisable +// +// Description: This function contains any flash specific code need to +// disable flash write +// +// Input: None +// +// Output: None +// +// Return: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +CommonSpiDeviceWriteDisable (VOID) +{ + // check is DeviceWrite enabled, if yes, disable it, + // if no, don't disable it. + if ( gbDeviceWriteEnabled ) { + gbDeviceWriteEnabled = 0; + } +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CommonSpiDeviceVirtualFixup +// +// Description: This function will be invoked by the core to convert +// runtime pointers to virtual address +// +// Input: *pRS Pointer to runtime services +// +// Output: None +// +// Return: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +static +VOID +CommonSpiDeviceVirtualFixup ( + IN EFI_RUNTIME_SERVICES *pRS +) +{ + +// // Following is an example code for virtual address conversion +// pRS->ConvertPointer(0, (VOID**)&FlashDeviceBase); + +//- SpiChipsetVirtualFixup(pRS); + pRS->ConvertPointer(0, (VOID **)&gSPIBASE); + pRS->ConvertPointer(0, (VOID **)&gRCBABASE); + gbDeviceVirtual = 1; + + return; +} +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//*************************************************************************
\ No newline at end of file |