| /* $NoKeywords:$ */ |
| /** |
| * @file |
| * |
| * PSP Base Library |
| * |
| * Contains interface to the PSP library |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: PSP |
| * @e \$Revision$ @e \$Date$ |
| * |
| */ |
| /***************************************************************************** |
| * |
| * Copyright (c) 2008 - 2016, Advanced Micro Devices, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| ***************************************************************************/ |
| |
| |
| /*---------------------------------------------------------------------------------------- |
| * M O D U L E S U S E D |
| *---------------------------------------------------------------------------------------- |
| */ |
| #include "AGESA.h" |
| #include "Filecode.h" |
| #include "Fch.h" |
| #include "PspBaseLib.h" |
| |
| #define FILECODE PROC_PSP_PSPBASELIB_PSPBASELIB_FILECODE |
| #define PSP_BAR_TMP_BASE 0xFEA00000ul |
| |
| #define GET_PCI_BUS(Reg) (((UINT32) Reg >> 16) & 0xFF) |
| #define GET_PCI_DEV(Reg) (((UINT32) Reg >> 11) & 0x1F) |
| #define GET_PCI_FUNC(Reg) (((UINT32) Reg >> 8) & 0x7) |
| #define GET_PCI_OFFSET(Reg) ((UINT32)Reg & 0xFF) |
| |
| #define PCI_CONFIG_SMU_INDIRECT_INDEX 0xB8 ///< Gnb Offset index for SMU mbox |
| #define PCI_CONFIG_SMU_INDIRECT_DATA 0xBC ///< Gnb Offset data for SMU mbox |
| |
| #define SMU_CC_PSP_FUSES_STATUS 0xC0018000ul ///< offset in GNB to find PSP fusing |
| #define SMU_CC_PSP_FUSES_SECURE BIT0 ///< BIT0 |
| #define SMU_CC_PSP_FUSES_FRA_ENABLE BIT1 ///< BIT1 |
| #define SMU_CC_PSP_FUSES_PROTO BIT2 ///< BIT2 |
| #define PLATFORM_SECURE_BOOT_EN BIT4 ///< BIT4 |
| |
| |
| #define PSP_BLANK_PART 0 ///< Blank part |
| #define PSP_PROTO_PART SMU_CC_PSP_FUSES_PROTO ///< Proto Part |
| #define PSP_NON_SECURE_PART (SMU_CC_PSP_FUSES_PROTO + SMU_CC_PSP_FUSES_PCPU_DIS) ///< Non Secure Part |
| #define PSP_SECURE_PART (SMU_CC_PSP_FUSES_PROTO + SMU_CC_PSP_FUSES_SECURE) ///< Secure Part |
| #define PSP_FRA_MODE (SMU_CC_PSP_FUSES_FRA_ENABLE + SMU_CC_PSP_FUSES_PROTO + SMU_CC_PSP_FUSES_SECURE) ///< FRA Part |
| |
| #define PSP_MUTEX_REG0_OFFSET (24 * 4) ///< PSP Mutex0 register offset |
| #define PSP_MUTEX_REG1_OFFSET (25 * 4) ///< PSP Mutex1 register offset |
| |
| #ifndef OFFSET_OF |
| #define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field)) |
| #endif |
| |
| /*---------------------------------------------------------------------------------------- |
| * D E F I N I T I O N S A N D M A C R O S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| |
| /*---------------------------------------------------------------------------------------- |
| * T Y P E D E F S A N D S T R U C T U R E S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| |
| /*---------------------------------------------------------------------------------------- |
| * P R O T O T Y P E S O F L O C A L F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| |
| |
| UINT32 |
| PspLibPciReadConfig ( |
| IN UINT32 Register |
| ) |
| { |
| UINT32 Value; |
| PCI_ADDR PciAddr; |
| |
| Value = 0; |
| PciAddr.AddressValue = MAKE_SBDFO (0, GET_PCI_BUS (Register), GET_PCI_DEV (Register), GET_PCI_FUNC (Register), GET_PCI_OFFSET (Register)); |
| |
| LibAmdPciRead (AccessWidth32, PciAddr, &Value, NULL); |
| |
| return Value; |
| } |
| |
| VOID |
| PspLibPciWriteConfig ( |
| IN UINT32 Register, |
| IN UINT32 Value |
| ) |
| { |
| PCI_ADDR PciAddr; |
| PciAddr.AddressValue = MAKE_SBDFO (0, GET_PCI_BUS (Register), GET_PCI_DEV (Register), GET_PCI_FUNC (Register), GET_PCI_OFFSET (Register)); |
| |
| LibAmdPciWrite (AccessWidth32, PciAddr, &Value, NULL); |
| |
| } |
| |
| UINT32 |
| PspLibPciReadPspConfig ( |
| IN UINT16 Offset |
| ) |
| { |
| return (PspLibPciReadConfig ((UINT32) (PSP_PCI_BDA + Offset))); |
| } |
| |
| VOID |
| PspLibPciWritePspConfig ( |
| IN UINT16 Offset, |
| IN UINT32 Value |
| ) |
| { |
| PspLibPciWriteConfig ((UINT32) (PSP_PCI_BDA + Offset), Value); |
| } |
| |
| /// Structure for Program ID |
| typedef enum { |
| CZ_PROGRAM = 0x00, ///< Program ID for CZ |
| BR_PROGRAM = 0x01, ///< Program ID for BR |
| ST_PROGRAM = 0x02, ///< Program ID for ST |
| UNSUPPORTED_PROGRAM = 0xFF, ///< Program ID for unsupported |
| } PROGRAM_ID; |
| |
| PROGRAM_ID |
| PspGetProgarmId ( |
| VOID |
| ) |
| { |
| CPUID_DATA Cpuid; |
| |
| LibAmdCpuidRead (0x00000001, &Cpuid, NULL); |
| //Stoney CPUID 0x00670F00 or 0x00670F01 |
| if ((Cpuid.EAX_Reg >> 16) == 0x67) { |
| return ST_PROGRAM; |
| } else if ((Cpuid.EAX_Reg >> 16) == 0x66) { |
| if ((Cpuid.EAX_Reg & 0xF0) == 0x50) { |
| //Bristol CPUID 0x00660F51 |
| return BR_PROGRAM; |
| } else if ((Cpuid.EAX_Reg & 0xF0) == 0x00) { |
| //Carrizo CPUID 0x00660F00 or 0x00660F01 |
| return CZ_PROGRAM; |
| } |
| } |
| return UNSUPPORTED_PROGRAM; |
| } |
| |
| BOOLEAN |
| GetPspDirBase ( |
| IN OUT UINT32 *Address |
| ) |
| { |
| UINTN i; |
| FIRMWARE_ENTRY_TABLE *FirmwareTableBase; |
| PROGRAM_ID ProgramId; |
| CONST UINT32 RomSigAddrTable[] = |
| { |
| 0xFFFA0000, // --> 512KB base |
| 0xFFF20000, // --> 1MB base |
| 0xFFE20000, // --> 2MB base |
| 0xFFC20000, // --> 4MB base |
| 0xFF820000, // --> 8MB base |
| 0xFF020000 // --> 16MB base |
| }; |
| |
| ProgramId = PspGetProgarmId (); |
| |
| for (i = 0; i < sizeof (RomSigAddrTable) / sizeof (UINT32); i++) { |
| FirmwareTableBase = (FIRMWARE_ENTRY_TABLE *) (UINTN) RomSigAddrTable[i]; |
| // Search flash for unique signature 0x55AA55AA |
| if (FirmwareTableBase->Signature == FIRMWARE_TABLE_SIGNATURE) { |
| switch (ProgramId) { |
| case BR_PROGRAM: |
| case CZ_PROGRAM: |
| *Address = FirmwareTableBase->PspDirBase; |
| break; |
| case ST_PROGRAM: |
| *Address = FirmwareTableBase->NewPspDirBase; |
| break; |
| default: |
| *Address = FirmwareTableBase->PspDirBase; |
| break; |
| } |
| return TRUE; |
| } |
| } |
| return (FALSE); |
| } |
| |
| /** |
| * Get specific PSP Entry information, this routine will auto detect the processor for loading |
| * correct PSP Directory |
| * |
| * |
| * |
| * @param[in] EntryType PSP DIR Entry Type |
| * @param[in,out] EntryAddress Address of the specific PSP Entry |
| * @param[in,out] EntrySize Size of the specific PSP Entry |
| */ |
| |
| BOOLEAN |
| PSPEntryInfo ( |
| IN PSP_DIRECTORY_ENTRY_TYPE EntryType, |
| IN OUT UINT64 *EntryAddress, |
| IN OUT UINT32 *EntrySize |
| ) |
| { |
| PSP_DIRECTORY *PspDir; |
| UINTN i; |
| PROGRAM_ID ProgramId; |
| |
| PspDir = NULL; |
| if (GetPspDirBase ((UINT32 *)&PspDir ) != TRUE) { |
| return FALSE; |
| } |
| |
| ProgramId = PspGetProgarmId (); |
| //Append BR Program ID |
| if ((ProgramId == BR_PROGRAM) && |
| ((EntryType == SMU_OFFCHIP_FW) || |
| (EntryType == SMU_OFF_CHIP_FW_2) || |
| (EntryType == AMD_SCS_BINARY))) { |
| EntryType |= (PSP_ENTRY_BR_PROGRAM_ID << 8); |
| } |
| |
| for (i = 0; i < PspDir->Header.TotalEntries; i++) { |
| if (PspDir->PspEntry[i].Type == EntryType) { |
| *EntryAddress = PspDir->PspEntry[i].Location; |
| *EntrySize = PspDir->PspEntry[i].Size; |
| return (TRUE); |
| } |
| } |
| |
| return (FALSE); |
| } |
| |
| BOOLEAN |
| PspSoftWareFuseInfo ( |
| IN OUT UINTN *FuseSpiAddress, |
| IN OUT UINT64 *FuseValue |
| ) |
| { |
| PSP_DIRECTORY *PspDir; |
| UINTN i; |
| |
| PspDir = NULL; |
| if (GetPspDirBase ((UINT32 *)&PspDir ) != TRUE) { |
| return FALSE; |
| } |
| |
| for (i = 0; i < PspDir->Header.TotalEntries; i++) { |
| if (PspDir->PspEntry[i].Type == AMD_SOFT_FUSE_CHAIN_01) { |
| *FuseSpiAddress = (UINT32) (UINTN) &PspDir->PspEntry[i].Location; |
| *FuseValue = PspDir->PspEntry[i].Location; |
| return (TRUE); |
| } |
| } |
| return (FALSE); |
| } |
| |
| UINT32 Fletcher32 ( |
| IN OUT UINT16 *data, |
| IN UINTN words |
| ) |
| { |
| UINT32 sum1; |
| UINT32 sum2; |
| UINTN tlen; |
| |
| sum1 = 0xffff; |
| sum2 = 0xffff; |
| |
| while (words) { |
| tlen = words >= 359 ? 359 : words; |
| words -= tlen; |
| do { |
| sum2 += sum1 += *data++; |
| } while (--tlen); |
| sum1 = (sum1 & 0xffff) + (sum1 >> 16); |
| sum2 = (sum2 & 0xffff) + (sum2 >> 16); |
| } |
| // Second reduction step to reduce sums to 16 bits |
| sum1 = (sum1 & 0xffff) + (sum1 >> 16); |
| sum2 = (sum2 & 0xffff) + (sum2 >> 16); |
| return sum2 << 16 | sum1; |
| } |
| |
| VOID |
| UpdataPspDirCheckSum ( |
| IN OUT PSP_DIRECTORY *PspDir |
| ) |
| { |
| PspDir->Header.Checksum = Fletcher32 ((UINT16 *) &PspDir->Header.TotalEntries, \ |
| (sizeof (PSP_DIRECTORY_HEADER) - OFFSET_OF (PSP_DIRECTORY_HEADER, TotalEntries) + PspDir->Header.TotalEntries * sizeof (PSP_DIRECTORY_ENTRY)) / 2); |
| } |
| |
| /** |
| Check if PSP device is present |
| |
| @retval BOOLEAN 0: PSP Disabled, 1: PSP Enabled |
| |
| **/ |
| BOOLEAN |
| CheckPspDevicePresent ( |
| VOID |
| ) |
| { |
| UINT32 SecureFuseReg; |
| PspLibPciWriteConfig ( (UINT32)PCI_CONFIG_SMU_INDIRECT_INDEX, (UINT32)SMU_CC_PSP_FUSES_STATUS); |
| SecureFuseReg = PspLibPciReadConfig ( (UINT32)PCI_CONFIG_SMU_INDIRECT_DATA); |
| |
| if (SecureFuseReg &= SMU_CC_PSP_FUSES_PROTO) { |
| return (TRUE); |
| } |
| return (FALSE); |
| } |
| |
| /** |
| Check PSP Platform Seucre Enable State |
| HVB & Secure S3 (Resume vector set to Dram, & core content will restore by uCode) |
| will be applied if Psp Plaform Secure is enabled |
| |
| @retval BOOLEAN 0: PSP Platform Secure Disabled, 1: PSP Platform Secure Enabled |
| |
| **/ |
| BOOLEAN |
| CheckPspPlatformSecureEnable ( |
| VOID |
| ) |
| { |
| UINT32 SecureFuseReg; |
| PspLibPciWriteConfig ( (UINT32)PCI_CONFIG_SMU_INDIRECT_INDEX, (UINT32)SMU_CC_PSP_FUSES_STATUS); |
| SecureFuseReg = PspLibPciReadConfig ( (UINT32)PCI_CONFIG_SMU_INDIRECT_DATA); |
| |
| if (SecureFuseReg &= PLATFORM_SECURE_BOOT_EN) { |
| return (TRUE); |
| } |
| return (FALSE); |
| } |
| |
| /** |
| Check PSP Recovery Flag |
| Target will set Recovery flag if some PSP entry point by PSP directory has been corrupted. |
| |
| @retval BOOLEAN 0: Recovery Flag is cleared, 1: Recovery Flag has been set |
| |
| **/ |
| BOOLEAN |
| CheckPspRecoveryFlag ( |
| VOID |
| ) |
| { |
| MBOX_STATUS *MboxStatus; |
| |
| //Init PSP MMIO |
| PspBarInitEarly (); |
| |
| GetPspMboxStatus (&MboxStatus); |
| |
| return (BOOLEAN) (MboxStatus->Recovery); |
| } |
| |
| /** |
| Return the PspMbox MMIO location |
| |
| |
| @retval BOOLEAN FALSE: ERROR, TRUE: SUCCEED |
| |
| **/ |
| BOOLEAN |
| GetPspMboxStatus ( |
| IN OUT MBOX_STATUS **MboxStatus |
| ) |
| { |
| UINT32 PspMmio; |
| |
| if (GetPspBar3Addr (&PspMmio) == FALSE) { |
| return (FALSE); |
| } |
| |
| *MboxStatus = (MBOX_STATUS *)( (UINTN)PspMmio + PSP_MAILBOX_BASE + PSP_MAILBOX_STATUS_OFFSET); // PSPMbox base is at offset CP2MSG_28 ie. offset 28*4 = 0x70 |
| |
| return (TRUE); |
| } |
| |
| BOOLEAN |
| PspBarInitEarly () |
| { |
| UINT32 PspMmioSize; |
| UINT32 Value32; |
| |
| if (PspLibPciReadPspConfig (PSP_PCI_DEVID_REG) == 0xffffffff) { |
| return (FALSE); |
| } |
| |
| //Check if PSP BAR has been assigned, if not do the PSP BAR initialation |
| if (PspLibPciReadPspConfig (PSP_PCI_BAR3_REG) == 0) { |
| /// Get PSP BAR1 Size |
| PspLibPciWritePspConfig (PSP_PCI_BAR3_REG, 0xFFFFFFFF); |
| PspMmioSize = PspLibPciReadPspConfig (PSP_PCI_BAR3_REG); |
| PspMmioSize = ~PspMmioSize + 1; |
| /// Assign BAR3 Temporary Address |
| PspLibPciWritePspConfig (PSP_PCI_BAR3_REG, PSP_BAR_TMP_BASE); |
| PspLibPciWritePspConfig ( PSP_PCI_CMD_REG, 0x06); |
| |
| /// Enable GNB redirection to this space @todo use equate & also find proper fix |
| PspLibPciWriteConfig ( ( (0x18 << 11) + (1 << 8) + 0xBC), ((PSP_BAR_TMP_BASE + PspMmioSize -1) >> 8) & ~0xFF); |
| PspLibPciWriteConfig ( ( (0x18 << 11) + (1 << 8) + 0xB8), (PSP_BAR_TMP_BASE >> 8) | 3); |
| /// Enable MsixBarEn, Bar1En, Bar3En |
| PspLibPciWritePspConfig ( PSP_PCI_EXTRAPCIHDR_REG, 0x34); |
| /// Capability chain update |
| Value32 = PspLibPciReadPspConfig (PSP_PCI_MIRRORCTRL1_REG); |
| Value32 &= ~D8F0x44_PmNxtPtrW_MASK; |
| Value32 |= 0xA4; |
| PspLibPciWritePspConfig (PSP_PCI_MIRRORCTRL1_REG, Value32); |
| } |
| |
| return (TRUE); |
| } |
| |
| /** |
| Return the PspMMIO MMIO location |
| |
| @param[in] PspMmio Pointer to Psp MMIO address |
| |
| @retval BOOLEAN 0: Error, 1 Success |
| **/ |
| BOOLEAN |
| GetPspBar1Addr ( |
| IN OUT UINT32 *PspMmio |
| ) |
| { |
| if (CheckPspDevicePresent () == FALSE) { |
| return (FALSE); |
| } |
| |
| *PspMmio = PspLibPciReadPspConfig (PSP_PCI_BAR1_REG); |
| |
| if ((*PspMmio) == 0xffffffff) { |
| return (FALSE); |
| } |
| |
| return (TRUE); |
| } |
| |
| /** |
| Return the PspMMIO MMIO location |
| |
| @param[in] PspMmio Pointer to Psp MMIO address |
| |
| @retval BOOLEAN 0: Error, 1 Success |
| **/ |
| BOOLEAN |
| GetPspBar3Addr ( |
| IN OUT UINT32 *PspMmio |
| ) |
| { |
| UINT32 PciReg48; |
| UINT64 MsrPspAddr; |
| |
| if (CheckPspDevicePresent () == FALSE) { |
| return (FALSE); |
| } |
| |
| PciReg48 = PspLibPciReadPspConfig (PSP_PCI_EXTRAPCIHDR_REG); |
| if (PciReg48 & BIT12) { |
| // D8F0x48[12] Bar3Hide |
| LibAmdMsrRead (PSP_MSR_PRIVATE_BLOCK_BAR, &MsrPspAddr, NULL); |
| *PspMmio = (UINT32)MsrPspAddr; |
| } else { |
| *PspMmio = PspLibPciReadPspConfig (PSP_PCI_BAR3_REG) & 0xFFF00000; |
| } |
| |
| if ((*PspMmio) == 0xffffffff) { |
| return (FALSE); |
| } |
| |
| return (TRUE); |
| } |
| /** |
| * Acquire the Mutex for access PSP,X86 co-accessed register |
| * Call this routine before access SMIx98 & SMIxA8 |
| * |
| */ |
| VOID |
| AcquirePspSmiRegMutex ( |
| VOID |
| ) |
| { |
| UINT32 PspBarAddr; |
| UINT32 MutexReg0; |
| UINT32 MutexReg1; |
| |
| PspBarAddr = 0; |
| if (GetPspBar3Addr (&PspBarAddr)) { |
| MutexReg0 = PspBarAddr + PSP_MUTEX_REG0_OFFSET; |
| MutexReg1 = PspBarAddr + PSP_MUTEX_REG1_OFFSET; |
| *(volatile UINT32*)(UINTN)(MutexReg0) |= BIT0; |
| *(volatile UINT32*)(UINTN)(MutexReg1) |= BIT0; |
| //Wait till PSP FW release the mutex |
| while ((*(volatile UINT32*)(UINTN)(MutexReg0)& BIT1) && (*(volatile UINT32*)(UINTN)(MutexReg1) & BIT0)) { |
| ; |
| } |
| } |
| } |
| /** |
| * Release the Mutex for access PSP,X86 co-accessed register |
| * Call this routine after access SMIx98 & SMIxA8 |
| * |
| */ |
| VOID |
| ReleasePspSmiRegMutex ( |
| VOID |
| ) |
| { |
| UINT32 PspBarAddr; |
| UINT32 MutexReg0; |
| |
| PspBarAddr = 0; |
| if (GetPspBar3Addr (&PspBarAddr)) { |
| MutexReg0 = PspBarAddr + PSP_MUTEX_REG0_OFFSET; |
| *(volatile UINT32*)(UINTN)(MutexReg0) &= ~BIT0; |
| } |
| } |
| |
| /*---------------------------------------------------------------------------------------*/ |
| /** |
| * Returns the access width mask for the processor |
| * |
| * |
| * @param[in] AccessWidth Access width |
| * @retval Width in number of bytes |
| */ |
| |
| |
| UINT8 |
| PspLibAccessWidth ( |
| IN ACCESS_WIDTH AccessWidth |
| ) |
| { |
| UINT8 Width; |
| |
| switch (AccessWidth) { |
| case AccessWidth8: |
| case AccessS3SaveWidth8: |
| Width = 1; |
| break; |
| case AccessWidth16: |
| case AccessS3SaveWidth16: |
| Width = 2; |
| break; |
| case AccessWidth32: |
| case AccessS3SaveWidth32: |
| Width = 4; |
| break; |
| case AccessWidth64: |
| case AccessS3SaveWidth64: |
| Width = 8; |
| break; |
| default: |
| Width = 0; |
| } |
| return Width; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Read GNB indirect registers |
| * |
| * |
| * |
| * @param[in] Address PCI address of indirect register |
| * @param[in] IndirectAddress Offset of indirect register |
| * @param[in] Width Width |
| * @param[out] Value Pointer to value |
| */ |
| VOID |
| PspLibPciIndirectRead ( |
| IN PCI_ADDR Address, |
| IN UINT32 IndirectAddress, |
| IN ACCESS_WIDTH Width, |
| OUT VOID *Value |
| ) |
| { |
| UINT32 IndexOffset; |
| |
| IndexOffset = PspLibAccessWidth (Width); |
| LibAmdPciWrite (Width, Address, &IndirectAddress, NULL); |
| Address.AddressValue += IndexOffset; |
| LibAmdPciRead (Width, Address, Value, NULL); |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Write GNB indirect registers |
| * |
| * |
| * |
| * @param[in] Address PCI address of indirect register |
| * @param[in] IndirectAddress Offset of indirect register |
| * @param[in] Width Width |
| * @param[in] Value Pointer to value |
| */ |
| VOID |
| PspLibPciIndirectWrite ( |
| IN PCI_ADDR Address, |
| IN UINT32 IndirectAddress, |
| IN ACCESS_WIDTH Width, |
| IN VOID *Value |
| ) |
| { |
| UINT32 IndexOffset; |
| |
| IndexOffset = PspLibAccessWidth (Width); |
| LibAmdPciWrite (Width, Address, &IndirectAddress, NULL); |
| Address.AddressValue += IndexOffset; |
| LibAmdPciWrite (Width, Address, Value, NULL); |
| } |
| |
| BOOLEAN |
| IsS3Resume ( |
| ) |
| { |
| UINT16 AcpiPm1CntBlk; |
| UINT16 SleepType; |
| UINT8 PmioAddr; |
| |
| AcpiPm1CntBlk = 0; |
| //Get AcpiPm1CntBlk address |
| //PMIO register can only allow 8bits access |
| PmioAddr = PMIO_REG62; |
| LibAmdIoWrite (AccessWidth8, PMIO_INDEX_PORT, &PmioAddr, NULL); |
| LibAmdIoRead (AccessWidth8, PMIO_DATA_PORT, &AcpiPm1CntBlk, NULL); |
| |
| PmioAddr++; |
| LibAmdIoWrite (AccessWidth8, PMIO_INDEX_PORT, &PmioAddr, NULL); |
| LibAmdIoRead (AccessWidth8, PMIO_DATA_PORT, ((UINT8 *) &AcpiPm1CntBlk) + 1, NULL); |
| |
| //Get Sleep type |
| LibAmdIoRead (AccessWidth16, AcpiPm1CntBlk, &SleepType, NULL); |
| SleepType = SleepType & 0x1C00; |
| SleepType = ((SleepType >> 10) & 7); |
| |
| return ((SleepType == 3) ? TRUE : FALSE); |
| } |
| |