diff options
Diffstat (limited to 'src/vendorcode/amd/pi/00670F00/Proc/Psp/PspBaseLib/PspBaseLib.c')
-rw-r--r-- | src/vendorcode/amd/pi/00670F00/Proc/Psp/PspBaseLib/PspBaseLib.c | 247 |
1 files changed, 231 insertions, 16 deletions
diff --git a/src/vendorcode/amd/pi/00670F00/Proc/Psp/PspBaseLib/PspBaseLib.c b/src/vendorcode/amd/pi/00670F00/Proc/Psp/PspBaseLib/PspBaseLib.c index 20a359ad0e..5c2410d7d4 100644 --- a/src/vendorcode/amd/pi/00670F00/Proc/Psp/PspBaseLib/PspBaseLib.c +++ b/src/vendorcode/amd/pi/00670F00/Proc/Psp/PspBaseLib/PspBaseLib.c @@ -9,12 +9,12 @@ * @xrefitem bom "File Content Label" "Release Content" * @e project: AGESA * @e sub-project: PSP - * @e \$Revision: 309090 $ @e \$Date: 2014-12-09 12:28:05 -0600 (Tue, 09 Dec 2014) $ + * @e \$Revision$ @e \$Date$ * */ /***************************************************************************** * - * Copyright (c) 2008 - 2015, Advanced Micro Devices, Inc. + * Copyright (c) 2008 - 2016, Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,10 +48,11 @@ */ #include "AGESA.h" #include "Filecode.h" +#include "Fch.h" #include "PspBaseLib.h" #define FILECODE PROC_PSP_PSPBASELIB_PSPBASELIB_FILECODE -#define PSP_BAR1_TMP_BASE 0xFEA00000ul +#define PSP_BAR_TMP_BASE 0xFEA00000ul #define GET_PCI_BUS(Reg) (((UINT32) Reg >> 16) & 0xFF) #define GET_PCI_DEV(Reg) (((UINT32) Reg >> 11) & 0x1F) @@ -74,6 +75,13 @@ #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 *---------------------------------------------------------------------------------------- @@ -139,6 +147,37 @@ PspLibPciWritePspConfig ( 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 @@ -146,6 +185,7 @@ GetPspDirBase ( { UINTN i; FIRMWARE_ENTRY_TABLE *FirmwareTableBase; + PROGRAM_ID ProgramId; CONST UINT32 RomSigAddrTable[] = { 0xFFFA0000, // --> 512KB base @@ -156,32 +196,66 @@ GetPspDirBase ( 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) { - *Address = FirmwareTableBase->PspDirBase; + 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 UINT32 *EntrySize + 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; @@ -193,6 +267,66 @@ PSPEntryInfo ( 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 @@ -273,7 +407,7 @@ GetPspMboxStatus ( { UINT32 PspMmio; - if (GetPspBar1Addr (&PspMmio) == FALSE) { + if (GetPspBar3Addr (&PspMmio) == FALSE) { return (FALSE); } @@ -283,7 +417,7 @@ GetPspMboxStatus ( } BOOLEAN -PspBarInitEarly (void) +PspBarInitEarly () { UINT32 PspMmioSize; UINT32 Value32; @@ -293,18 +427,18 @@ PspBarInitEarly (void) } //Check if PSP BAR has been assigned, if not do the PSP BAR initialation - if (PspLibPciReadPspConfig (PSP_PCI_BAR1_REG) == 0) { + if (PspLibPciReadPspConfig (PSP_PCI_BAR3_REG) == 0) { /// Get PSP BAR1 Size - PspLibPciWritePspConfig (PSP_PCI_BAR1_REG, 0xFFFFFFFF); - PspMmioSize = PspLibPciReadPspConfig (PSP_PCI_BAR1_REG); + PspLibPciWritePspConfig (PSP_PCI_BAR3_REG, 0xFFFFFFFF); + PspMmioSize = PspLibPciReadPspConfig (PSP_PCI_BAR3_REG); PspMmioSize = ~PspMmioSize + 1; - /// Assign BAR1 Temporary Address - PspLibPciWritePspConfig (PSP_PCI_BAR1_REG, PSP_BAR1_TMP_BASE); + /// 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_BAR1_TMP_BASE + PspMmioSize -1) >> 8) & ~0xFF); - PspLibPciWriteConfig ( ( (0x18 << 11) + (1 << 8) + 0xB8), (PSP_BAR1_TMP_BASE >> 8) | 3); + 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 @@ -354,11 +488,21 @@ GetPspBar3Addr ( IN OUT UINT32 *PspMmio ) { + UINT32 PciReg48; + UINT64 MsrPspAddr; + if (CheckPspDevicePresent () == FALSE) { return (FALSE); } - *PspMmio = PspLibPciReadPspConfig (PSP_PCI_BAR3_REG); + 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); @@ -366,6 +510,51 @@ GetPspBar3Addr ( 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; + } +} /*---------------------------------------------------------------------------------------*/ /** @@ -461,4 +650,30 @@ PspLibPciIndirectWrite ( 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); +} |