blob: 20a359ad0e24307fdaead64b44f5cf18f6f815c9 [file] [log] [blame]
/* $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: 309090 $ @e \$Date: 2014-12-09 12:28:05 -0600 (Tue, 09 Dec 2014) $
*
*/
/*****************************************************************************
*
* Copyright (c) 2008 - 2015, 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 "PspBaseLib.h"
#define FILECODE PROC_PSP_PSPBASELIB_PSPBASELIB_FILECODE
#define PSP_BAR1_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
/*----------------------------------------------------------------------------------------
* 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);
}
BOOLEAN
GetPspDirBase (
IN OUT UINT32 *Address
)
{
UINTN i;
FIRMWARE_ENTRY_TABLE *FirmwareTableBase;
CONST UINT32 RomSigAddrTable[] =
{
0xFFFA0000, // --> 512KB base
0xFFF20000, // --> 1MB base
0xFFE20000, // --> 2MB base
0xFFC20000, // --> 4MB base
0xFF820000, // --> 8MB base
0xFF020000 // --> 16MB base
};
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;
return TRUE;
}
}
return (FALSE);
}
BOOLEAN
PSPEntryInfo (
IN PSP_DIRECTORY_ENTRY_TYPE EntryType,
IN OUT UINT64 *EntryAddress,
IN UINT32 *EntrySize
)
{
PSP_DIRECTORY *PspDir;
UINTN i;
if (GetPspDirBase ((UINT32 *)&PspDir ) != TRUE) {
return FALSE;
}
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);
}
/**
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 (GetPspBar1Addr (&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 (void)
{
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_BAR1_REG) == 0) {
/// Get PSP BAR1 Size
PspLibPciWritePspConfig (PSP_PCI_BAR1_REG, 0xFFFFFFFF);
PspMmioSize = PspLibPciReadPspConfig (PSP_PCI_BAR1_REG);
PspMmioSize = ~PspMmioSize + 1;
/// Assign BAR1 Temporary Address
PspLibPciWritePspConfig (PSP_PCI_BAR1_REG, PSP_BAR1_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);
/// 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
)
{
if (CheckPspDevicePresent () == FALSE) {
return (FALSE);
}
*PspMmio = PspLibPciReadPspConfig (PSP_PCI_BAR3_REG);
if ((*PspMmio) == 0xffffffff) {
return (FALSE);
}
return (TRUE);
}
/*---------------------------------------------------------------------------------------*/
/**
* 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);
}