blob: 5862768bb0a20753f59414cc00f23c251f83237d [file] [log] [blame]
/**
* @file
*
* NB library functions.
*
*
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: CIMx-NB
* @e sub-project:
* @e \$Revision:$ @e \$Date:$
*
*/
/*****************************************************************************
*
* Copyright (C) 2012 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 "NbPlatform.h"
#include "amdDebugOutLib.h"
/*----------------------------------------------------------------------------------------
* 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
*----------------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------------------
* E X P O R T E D F U N C T I O N S
*----------------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------------------*/
/**
* Get silicon type and revision info.
*
*
*
* @param[in] NbConfigPtr configuration structure pointer.
* @retval NB_INFO Northbrige Info Structure.
*/
/*----------------------------------------------------------------------------------------*/
NB_INFO
LibNbGetRevisionInfo (
IN AMD_NB_CONFIG *NbConfigPtr
)
{
NB_INFO RevisionInfo;
UINT16 DeviceId;
UINT8 RevisionId;
UINT32 PrivateId;
LibNbPciRead (NbConfigPtr->NbPciAddress.AddressValue | 0x8, AccessWidth8, &RevisionId, NbConfigPtr);
RevisionInfo.Revision = RevisionId;
LibNbPciRead (NbConfigPtr->NbPciAddress.AddressValue | 0x2, AccessWidth16, &DeviceId, NbConfigPtr);
switch (DeviceId) {
case 0x5956:
RevisionInfo.Type = NB_RD890TV;
break;
case 0x5957:
RevisionInfo.Type = NB_RX780;
break;
case 0x5958:
RevisionInfo.Type = NB_RD780;
break;
case 0x5A10:
RevisionInfo.Type = NB_SR5690;
break;
case 0x5A11:
RevisionInfo.Type = NB_RD890;
break;
case 0x5A12:
RevisionInfo.Type = NB_SR5670;
break;
case 0x5A13:
RevisionInfo.Type = NB_SR5650;
break;
case 0x5A14:
RevisionInfo.Type = NB_990FX;
LibNbPciIndexRead (NbConfigPtr->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG7D, AccessWidth32, &PrivateId, NbConfigPtr);
PrivateId = (PrivateId >> 21) & 0x0f;
if (PrivateId == 1) {
RevisionInfo.Type = NB_990FX;
}
if (PrivateId == 2) {
RevisionInfo.Type = NB_990X;
}
if (PrivateId == 3) {
RevisionInfo.Type = NB_970;
}
break;
default:
RevisionInfo.Type = NB_UNKNOWN;
CIMX_ASSERT (FALSE);
}
return RevisionInfo;
}
/*----------------------------------------------------------------------------------------*/
/**
* Call Back routine.
*
*
*
* @param[in] CallBackId Callback ID.
* @param[in] Data Callback specific data.
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
AGESA_STATUS
LibNbCallBack (
IN UINT32 CallBackId,
IN OUT UINTN Data,
IN OUT AMD_NB_CONFIG *NbConfigPtr
)
{
AGESA_STATUS Status;
CALLOUT_ENTRY CallBackPtr = GET_BLOCK_CONFIG_PTR (NbConfigPtr)->StandardHeader.CalloutPtr;
Status = AGESA_UNSUPPORTED;
if (CallBackPtr != NULL) {
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NB_TRACE), "[NBLIB]LibNbCallBack CallBackId = 0x%x\n", CallBackId));
Status = (*CallBackPtr) (CallBackId, Data, GET_BLOCK_CONFIG_PTR (NbConfigPtr));
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NB_TRACE), "[NBLIB]LibNbCallBack Return = 0x%x\n", Status));
}
return Status;
}
/*----------------------------------------------------------------------------------------*/
/**
* Call Back routine.
*
*
*
* @param[in] SystemApi Pointer to System API
* @param[in] ConfigPtr Northbridge block configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
AGESA_STATUS
LibSystemApiCall (
IN SYSTEM_API SystemApi,
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
)
{
API_WORKSPACE Workspace;
UINT8 NorthbridgeId;
LibAmdMemFill (&Workspace, 0, sizeof (API_WORKSPACE), (AMD_CONFIG_PARAMS *)&(ConfigPtr->StandardHeader));
Workspace.ConfigPtr = ConfigPtr;
Workspace.Status = AGESA_SUCCESS;
for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) {
ConfigPtr->Northbridges[NorthbridgeId].ConfigPtr = &Workspace.ConfigPtr;
}
if (SystemApi != NULL) {
(*SystemApi)(ConfigPtr);
}
return Workspace.Status;
}
/*----------------------------------------------------------------------------------------*/
/**
* Call Back routine.
*
*
*
* @param[in] NbApi Pointer to NB API
* @param[in] ConfigPtr Northbridge block configuration structure pointer
*/
/*----------------------------------------------------------------------------------------*/
AGESA_STATUS
LibNbApiCall (
IN NB_API NbApi,
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
)
{
UINT8 NorthbridgeId;
AGESA_STATUS Status;
Status = AGESA_SUCCESS;
for (NorthbridgeId = 0; NorthbridgeId <= ConfigPtr->NumberOfNorthbridges; NorthbridgeId++) {
AMD_NB_CONFIG *NbConfigPtr = &ConfigPtr->Northbridges[NorthbridgeId];
ConfigPtr->CurrentNorthbridge = NorthbridgeId;
if (!LibNbIsDevicePresent (NbConfigPtr->NbPciAddress, NbConfigPtr)) {
REPORT_EVENT (AGESA_WARNING, GENERAL_ERROR_NB_NOT_PRESENT, 0 , 0, 0, 0, NbConfigPtr);
continue;
}
if (NbApi != NULL) {
Status = (*NbApi) (NbConfigPtr);
if (Status == AGESA_FATAL) {
break;
}
}
}
return Status;
}
/*----------------------------------------------------------------------------------------*/
/**
* Write PCI register.
*
*
*
* @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue
* @param[in] Width Access width.
* @param[in] Value Pointer to new register value.
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbPciWrite (
IN UINT32 Address,
IN ACCESS_WIDTH Width,
IN VOID *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
PCI_ADDR DeviceAddress;
DeviceAddress.AddressValue = Address;
LibAmdPciWrite (Width, DeviceAddress, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
}
/*----------------------------------------------------------------------------------------*/
/**
* Read PCI register
*
*
*
* @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue
* @param[in] Width Access width.
* @param[in] Value Pointer to save register value.
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbPciRead (
IN UINT32 Address,
IN ACCESS_WIDTH Width,
OUT VOID *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
PCI_ADDR DeviceAddress;
DeviceAddress.AddressValue = Address;
LibAmdPciRead (Width, DeviceAddress, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
}
/*----------------------------------------------------------------------------------------*/
/**
* Read/Modify/Write PCI register
*
*
*
* @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue
* @param[in] Width Access width.
* @param[in] Mask AND Mask.
* @param[in] Data OR Mask.
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbPciRMW (
IN UINT32 Address,
IN ACCESS_WIDTH Width,
IN UINT32 Mask,
IN UINT32 Data,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 Value;
LibNbPciRead (Address, Width, &Value, NbConfigPtr);
Value = (Value & Mask) | Data;
LibNbPciWrite (Address, Width, &Value, NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Read PCI Index/Data Address space
*
*
*
* @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue
* @param[in] Index Index Address.
* @param[in] Width Access width of Index/Data register.
* @param[in] Value Pointer to save register value.
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbPciIndexRead (
IN UINT32 Address,
IN UINT32 Index,
IN ACCESS_WIDTH Width,
OUT UINT32 *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 IndexOffset;
IndexOffset = (1 << ((Width < 0x80)? (Width - 1): (Width - 0x81)));
LibNbPciWrite (Address, Width, &Index, NbConfigPtr);
LibNbPciRead (Address + IndexOffset, Width, Value, NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Write PCI Index/Data Address space
*
*
*
* @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue
* @param[in] Index Index Address.
* @param[in] Width Access width of Index/Data register.
* @param[in] Value Pointer to save register value.
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbPciIndexWrite (
IN UINT32 Address,
IN UINT32 Index,
IN ACCESS_WIDTH Width,
IN UINT32 *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 IndexOffset;
IndexOffset = (1 << ((Width < 0x80)? (Width - 1): (Width - 0x81)));
LibNbPciWrite (Address, Width, &Index, NbConfigPtr);
LibNbPciWrite (Address + IndexOffset , Width, Value, NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Read/Modify/Write PCI Index/Data Address space
*
*
*
* @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue
* @param[in] Index Index Address.
* @param[in] Width Access width of Index/Data register.
* @param[in] Mask AND Mask.
* @param[in] Data OR Mask.
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbPciIndexRMW (
IN UINT32 Address,
IN UINT32 Index,
IN ACCESS_WIDTH Width,
IN UINT32 Mask,
IN UINT32 Data,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 Value;
LibNbPciIndexRead (Address, Index, Width, &Value, NbConfigPtr);
Value = (Value & Mask) | Data;
LibNbPciIndexWrite (Address, Index, Width, &Value, NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Program table of indirect register.
*
*
*
* @param[in] Address Compressed PCIE address identical to PCI_ADDR.AddressValue
* @param[in] Index Index Address. Index address OR with INDIRECT_REG_ENTRY.Register
* @param[in] pTable Pointer to indirect register table.
* @param[in] Length Number of entry in indirect register table.
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbIndirectTableInit (
IN UINT32 Address,
IN UINT32 Index,
IN INDIRECT_REG_ENTRY *pTable,
IN UINTN Length,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINTN i;
for (i = 0; i < Length; i++) {
LibNbPciIndexRMW (Address, Index | pTable[i].Register , AccessS3SaveWidth32, pTable[i].Mask, pTable[i].Data, NbConfigPtr);
}
}
/*----------------------------------------------------------------------------------------*/
/*
* Find PCI capability pointer
*
*
*
*
*
*/
/*----------------------------------------------------------------------------------------*/
UINT8
LibNbFindPciCapability (
IN UINT32 Address,
IN UINT8 CapabilityId,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT8 CapabilityPtr;
UINT8 CurrentCapabilityId;
PCI_ADDR Device;
Device.AddressValue = Address;
CapabilityPtr = 0x34;
if (!LibNbIsDevicePresent (Device, NbConfigPtr)) {
return 0;
}
while (CapabilityPtr != 0) {
LibNbPciRead (Address | CapabilityPtr, AccessWidth8 , &CapabilityPtr, NbConfigPtr);
if (CapabilityPtr) {
LibNbPciRead (Address | CapabilityPtr , AccessWidth8 , &CurrentCapabilityId, NbConfigPtr);
if (CurrentCapabilityId == CapabilityId) break;
CapabilityPtr++;
}
}
return CapabilityPtr;
}
/*----------------------------------------------------------------------------------------*/
/*
* Find PCIe extended capability pointer
*
*
*
*
*
*/
/*----------------------------------------------------------------------------------------*/
UINT16
LibNbFindPcieExtendedCapability (
IN UINT32 Address,
IN UINT16 ExtendedCapabilityId,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT16 CapabilityPtr;
UINT32 ExtendedCapabilityIdBlock;
if (LibNbFindPciCapability (Address, 0x10, NbConfigPtr) != 0) {
CapabilityPtr = 0x100;
LibNbPciRead (Address | CapabilityPtr , AccessWidth32 , &ExtendedCapabilityIdBlock, NbConfigPtr);
if (ExtendedCapabilityIdBlock != 0 && (UINT16)ExtendedCapabilityIdBlock != 0xffff) {
do {
if ((UINT16)ExtendedCapabilityIdBlock == ExtendedCapabilityId) {
return CapabilityPtr;
}
CapabilityPtr = (UINT16) ((ExtendedCapabilityIdBlock >> 20) & 0xfff);
LibNbPciRead (Address | CapabilityPtr , AccessWidth32 , &ExtendedCapabilityIdBlock, NbConfigPtr);
} while (CapabilityPtr != 0);
}
}
return 0;
}
/*----------------------------------------------------------------------------------------*/
/**
* Read IO space
*
*
*
* @param[in] Address IO Port address.
* @param[in] Width Access width
* @param[in] Value Pointer to save IO port value;
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbIoRead (
IN UINT16 Address,
IN ACCESS_WIDTH Width,
OUT VOID *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
LibAmdIoRead (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
}
/*----------------------------------------------------------------------------------------*/
/**
* Write IO space
*
*
*
* @param[in] Address IO Port address.
* @param[in] Width Access width
* @param[in] Value Pointer to new IO port value
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
VOID
LibNbIoWrite (
IN UINT16 Address,
IN ACCESS_WIDTH Width,
IN VOID *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
LibAmdIoWrite (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
}
/*----------------------------------------------------------------------------------------*/
/**
* Read/Modify/Write IO space
*
*
*
* @param[in] Address IO Port address.
* @param[in] Width Access width
* @param[in] Mask AND Mask
* @param[in] Data OR Mask
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbIoRMW (
IN UINT16 Address,
IN ACCESS_WIDTH Width,
IN UINT32 Mask,
IN UINT32 Data,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 Value;
LibNbIoRead (Address, Width, &Value, NbConfigPtr);
Value = (Value & Mask) | Data;
LibNbIoWrite (Address, Width, &Value, NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Read CPU HT link Phy register
*
*
*
* @param[in] Node Node device Address (0x18 - Node 0, 0x19 - Mode 1 etc.)
* @param[in] Link HT Link ID (0 - Link 0, 1 - Link 1 etc.)
* @param[in] Register Register address.
* @param[in] Value Pointer to save register value
* @param[in] NbConfigPtr Northbridge configuration block pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbCpuHTLinkPhyRead (
IN UINT8 Node,
IN UINT8 Link,
IN UINT16 Register,
OUT UINT32 *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 Data;
PCI_ADDR CpuPciAddress;
UINT8 LinkId;
LinkId = Link & 0xf;
CpuPciAddress.AddressValue = MAKE_SBDFO (0, 0, Node, 4, 0);
LibNbPciRMW (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, 0x0, Register | ((Register & 0xfe00)?BIT29:0), NbConfigPtr);
do {
LibNbPciRead (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, &Data, NbConfigPtr);
} while ((Data & BIT31) == 0);
LibNbPciRead (CpuPciAddress.AddressValue | (LinkId * 8 + 0x184), AccessWidth32, Value, NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Write CPU HT link Phy register
*
*
*
* @param[in] Node Node device Address (0x18 - Node 0, 0x19 - Mode 1 etc.)
* @param[in] Link HT Link ID (0 - Link 0, 1 - Link 1 etc.)
* @param[in] Register Register address.
* @param[in] Value Pointer to new register value
* @param[in] NbConfigPtr Northbridge configuration block pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbCpuHTLinkPhyWrite (
IN UINT8 Node,
IN UINT8 Link,
IN UINT16 Register,
IN UINT32 *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 Data;
PCI_ADDR CpuPciAddress;
UINT8 LinkId;
LinkId = Link & 0xf;
CpuPciAddress.AddressValue = MAKE_SBDFO (0, 0, Node, 4, 0);
LibNbPciWrite (CpuPciAddress.AddressValue | (LinkId * 8 + 0x184), AccessWidth32, Value, NbConfigPtr);
LibNbPciRMW (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, 0x0, Register | BIT30 | ((Register & 0xfe00)?BIT29:0), NbConfigPtr);
do {
LibNbPciRead (CpuPciAddress.AddressValue | (LinkId * 8 + 0x180), AccessWidth32, &Data, NbConfigPtr);
} while ((Data & BIT31) == 0);
}
/*----------------------------------------------------------------------------------------*/
/**
* Read/Modify/Write CPU HT link Phy register
*
*
*
* @param[in] Node Node device Address (0x18 - Node 0, 0x19 - Mode 1 etc.)
* @param[in] Link HT Link ID (0 - Link 0, 1 - Link 1 etc.)
* @param[in] Register Register address.
* @param[in] Mask AND Mask.
* @param[in] Data OR Mask.
* @param[in] NbConfigPtr Northbridge configuration block pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbCpuHTLinkPhyRMW (
IN UINT8 Node,
IN UINT8 Link,
IN UINT16 Register,
IN UINT32 Mask,
IN UINT32 Data,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 Value;
LibNbCpuHTLinkPhyRead (Node, Link, Register, &Value, NbConfigPtr);
Value = (Value & Mask) | Data;
LibNbCpuHTLinkPhyWrite (Node, Link, Register, &Value, NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Enable Clock Config space access.
* Enable access to Clock Config Space at 0:0:1 PCI address.
*
*
* @param[in] pConfig Northbridge configuration block pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbEnableClkConfig (
IN AMD_NB_CONFIG *pConfig
)
{
LibNbPciRMW (NB_SBDFO | NB_PCI_REG4C, AccessS3SaveWidth8, (UINT32)~BIT0, BIT0, pConfig);
}
/*----------------------------------------------------------------------------------------*/
/**
* Disable Clock Config space access.
* Disable access to Clock Config Space at 0:0:1 PCI address.
*
*
* @param[in] pConfig Northbridge configuration block pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbDisableClkConfig (
IN AMD_NB_CONFIG *pConfig
)
{
LibNbPciRMW (NB_SBDFO | NB_PCI_REG4C, AccessS3SaveWidth8, (UINT32)~BIT0, 0x0 , pConfig);
}
/*----------------------------------------------------------------------------------------*/
/**
* Check if PCI Device Present
*
*
*
* @param[in] Device Device PCI address.
* @param[in] NbConfigPtr Northbridge configuration block pointer.
*
* @retval TRUE Device present.
* @retval FALSE Device not present.
*/
/*----------------------------------------------------------------------------------------*/
BOOLEAN
LibNbIsDevicePresent (
IN PCI_ADDR Device,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 VendorId;
LibNbPciRead (Device.AddressValue, AccessWidth32, &VendorId, NbConfigPtr);
return (VendorId == 0xffffffff)?FALSE:TRUE;
}
/*----------------------------------------------------------------------------------------*/
/**
* Check if IOMMU enabled
*
*
*
* @param[in] NbConfigPtr Northbridge configuration block pointer.
*
* @retval TRUE IOMMU not enabled.
* @retval FALSE IOMMU not enabled.
*/
/*----------------------------------------------------------------------------------------*/
BOOLEAN
LibNbIsIommuEnabled (
IN AMD_NB_CONFIG *NbConfigPtr
)
{
PCI_ADDR IommuAddress;
IommuAddress.AddressValue = NbConfigPtr->NbPciAddress.AddressValue;
IommuAddress.Address.Function = 2;
if (LibNbIsDevicePresent (IommuAddress, NbConfigPtr)) {
UINT8 Value;
LibNbPciRead (IommuAddress.AddressValue | 0x44, AccessWidth8, &Value, NbConfigPtr);
if ((Value & BIT0) != 0) {
return TRUE;
}
}
return FALSE;
}
/*----------------------------------------------------------------------------------------*/
/**
* Reverse bit in DWORD.
* Reverse bits in bitfield inside DWORD.
*
*
* @param[in] Data Value to reverse.
* @param[in] StartBit Start bit.
* @param[in] StopBit Stop bit.
* @retval Reversed Value.
*/
/*----------------------------------------------------------------------------------------*/
UINT32
LibNbBitReverse (
IN UINT32 Data,
IN UINT8 StartBit,
IN UINT8 StopBit
)
{
UINT32 Bitr;
UINT32 Bitl;
UINT32 Distance;
while (StartBit < StopBit) {
Bitr = Data & (1 << StartBit );
Bitl = Data & (1 << StopBit );
Distance = StopBit - StartBit;
Data = (Data & ((UINT32)~(Bitl | Bitr))) | (Bitr << Distance ) | (Bitl >> Distance);
StartBit++;
StopBit--;
}
return Data;
}
/*----------------------------------------------------------------------------------------*/
/**
* Read CPU family
*
*
*
* @retval 0xXX00000 CPU family.
*
*/
UINT32
LibNbGetCpuFamily (
VOID
)
{
CPUID_DATA Cpuid;
CpuidRead (0x1, &Cpuid);
return Cpuid.EAX_Reg & 0xff00000;
}
/*----------------------------------------------------------------------------------------*/
/**
* Load Firmware block
*
*
*
* @param[in] Address Address to load firmware
* @param[in] Size Firmware block size
* @param[in] FirmwareBlockPtr Pointer to firmware block
* @param[in] NbConfigPtr Northbridge configuration block pointer.
*
*/
VOID
LibNbLoadMcuFirmwareBlock (
IN UINT16 Address,
IN UINT16 Size,
IN UINT32 *FirmwareBlockPtr,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 i;
PCI_ADDR ClkPciAddress;
UINT32 Selector;
Selector = (Address >= 0x200)?0x0000000:0x10000;
ClkPciAddress = NbConfigPtr->NbPciAddress;
ClkPciAddress.Address.Function = 1;
LibNbEnableClkConfig (NbConfigPtr);
for (i = 0; i < Size; i++) {
LibNbPciIndexWrite (ClkPciAddress.AddressValue | MC_CLK_INDEX, Selector | (Address + (i * 4)), AccessWidth32, &FirmwareBlockPtr[i], NbConfigPtr);
}
LibNbDisableClkConfig (NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Read SMU firmware ram
*
*
*
* @param[in] Address Address to read
* @param[in] NbConfigPtr Northbridge configuration block pointer.
*
*/
UINT32
LibNbReadMcuRam (
IN UINT16 Address,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 Value;
PCI_ADDR ClkPciAddress;
UINT32 Selector;
Selector = (Address >= 0x200) ? 0x0000000 : 0x10000;
ClkPciAddress = NbConfigPtr->NbPciAddress;
ClkPciAddress.Address.Function = 1;
LibNbEnableClkConfig (NbConfigPtr);
LibNbPciIndexRead (ClkPciAddress.AddressValue | MC_CLK_INDEX, Selector | (Address), AccessWidth32, &Value, NbConfigPtr);
LibNbDisableClkConfig (NbConfigPtr);
return Value;
}
/*----------------------------------------------------------------------------------------*/
/**
* MCU Control
*
*
*
* @param[in] Operation Set/Reset MCU controller
* @param[in] NbConfigPtr Northbridge configuration block pointer.
*/
VOID
LibNbMcuControl (
IN NB_MCU_MODE Operation,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
PCI_ADDR ClkPciAddress;
UINT32 Value;
Value = (Operation == AssertReset)?0x00000ee1:0x00000ee2;
ClkPciAddress = NbConfigPtr->NbPciAddress;
ClkPciAddress.Address.Function = 1;
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (NbConfigPtr), CIMX_NBPCIE_TRACE), "LibNbMcuControl Operation [0x%x]\n", Operation));
LibNbEnableClkConfig (NbConfigPtr);
LibNbPciIndexWrite (ClkPciAddress.AddressValue | MC_CLK_INDEX, 0x00030000, AccessWidth32, &Value, NbConfigPtr);
LibNbDisableClkConfig (NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Read/Modify/Write memory space
*
*
*
* @param[in] Address Memory address.
* @param[in] Width Access width
* @param[in] Mask AND Mask
* @param[in] Data OR Mask
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbMemRMW (
IN UINT64 Address,
IN ACCESS_WIDTH Width,
IN UINT32 Mask,
IN UINT32 Data,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
UINT32 Value;
LibNbMemRead (Address, Width, &Value, NbConfigPtr);
Value = (Value & Mask) | Data;
LibNbMemWrite (Address, Width, &Value, NbConfigPtr);
}
/*----------------------------------------------------------------------------------------*/
/**
* Read memory space
*
*
*
* @param[in] Address Memory address.
* @param[in] Width Access width
* @param[in] Value Pointer to memory to store value
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbMemRead (
IN UINT64 Address,
IN ACCESS_WIDTH Width,
IN VOID *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
LibAmdMemRead (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
}
/*----------------------------------------------------------------------------------------*/
/**
* Write memory space
*
*
*
* @param[in] Address Memory address.
* @param[in] Width Access width
* @param[in] Value Pointer to memory to get value
* @param[in] NbConfigPtr Northbridge configuration structure pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbMemWrite (
IN UINT64 Address,
IN ACCESS_WIDTH Width,
OUT VOID *Value,
IN AMD_NB_CONFIG *NbConfigPtr
)
{
LibAmdMemWrite (Width, Address, Value, (AMD_CONFIG_PARAMS *)((NbConfigPtr == NULL)?NULL:GET_BLOCK_CONFIG_PTR (NbConfigPtr)));
}
/*----------------------------------------------------------------------------------------*/
/**
* Scan Pci Bridge
*
*
*
* @param[in] This Pointer to PCI topology scan protocol
* @param[in] Bridge Address of PCI to PCI bridge to scan.
*/
SCAN_STATUS
LibNbScanPciBridgeBuses (
IN PCI_SCAN_PROTOCOL *This,
IN PCI_ADDR Bridge
)
{
SCAN_STATUS Status;
UINT8 CurrentBus;
UINT8 MinBus;
UINT8 MaxBus;
PCI_ADDR Device;
CIMX_ASSERT (This != NULL);
if (This->ScanBus == NULL) {
return SCAN_FINISHED;
}
LibNbPciRead (Bridge.AddressValue | 0x19, AccessWidth8, &MinBus, This->pConfig);
LibNbPciRead (Bridge.AddressValue | 0x1A, AccessWidth8, &MaxBus, This->pConfig);
if (MinBus == 0 || MaxBus == 0) {
return SCAN_FINISHED;
}
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (This->pConfig), CIMX_NBPCIE_TRACE), " Scan bridge %d:%d:%d \n", Bridge.Address.Bus, Bridge.Address.Device, Bridge.Address.Function));
for (CurrentBus = MinBus; CurrentBus <= MaxBus; CurrentBus++) {
Device.AddressValue = MAKE_SBDFO (0, CurrentBus, 0, 0, 0);
Status = This->ScanBus (This, Device);
}
return SCAN_FINISHED;
}
/*----------------------------------------------------------------------------------------*/
/**
* Scan Pci Bus
*
*
*
* @param[in] This Pointer to PCI topology scan protocol
* @param[in] Device Pci address device to start bus scan from
*/
/*----------------------------------------------------------------------------------------*/
SCAN_STATUS
LibNbScanPciBus (
IN PCI_SCAN_PROTOCOL *This,
IN PCI_ADDR Device
)
{
SCAN_STATUS Status;
UINT32 CurrentDevice;
CIMX_ASSERT (This != NULL);
if (This->ScanDevice == NULL) {
return SCAN_FINISHED;
}
for (CurrentDevice = Device.Address.Device; CurrentDevice <= 0x1f; CurrentDevice++) {
Device.Address.Device = CurrentDevice;
if (LibNbIsDevicePresent (Device, This->pConfig)) {
Status = This->ScanDevice (This, Device);
if (Status == SCAN_STOP_BUS_ENUMERATION) {
return Status;
}
}
}
return SCAN_FINISHED;
}
/*----------------------------------------------------------------------------------------*/
/**
* Scan Pci Device
*
*
*
* @param[in] This Pointer to PCI topology scan protocol
* @param[in] Device Pci address device to scan
*/
/*----------------------------------------------------------------------------------------*/
SCAN_STATUS
LibNbScanPciDevice (
IN PCI_SCAN_PROTOCOL *This,
IN PCI_ADDR Device
)
{
SCAN_STATUS Status;
UINT8 Header;
UINT32 CurrentFunction;
UINT32 MaxFunction;
CIMX_ASSERT (This != NULL);
if (This->ScanFunction == NULL) {
return SCAN_FINISHED;
}
LibNbPciRead (Device.AddressValue | 0x0E , AccessWidth8, &Header, This->pConfig);
MaxFunction = (Header & 0x80)?7:0;
for (CurrentFunction = Device.Address.Function; CurrentFunction <= MaxFunction; CurrentFunction++) {
Device.Address.Function = CurrentFunction;
if (LibNbIsDevicePresent (Device, This->pConfig)) {
CIMX_TRACE ((TRACE_DATA (GET_BLOCK_CONFIG_PTR (This->pConfig), CIMX_NBPCIE_TRACE), " Scan function %d:%d:%d \n", Device.Address.Bus, Device.Address.Device, Device.Address.Function));
Status = This->ScanFunction (This, Device);
if (Status == SCAN_STOP_DEVICE_ENUMERATION || Status == SCAN_STOP_BUS_ENUMERATION) {
return Status;
}
}
}
return SCAN_FINISHED;
}
/*----------------------------------------------------------------------------------------*/
/**
* Set default Indexes
*
*
* @param[in] NbConfigPtr Northbridge configuration block pointer.
*/
/*----------------------------------------------------------------------------------------*/
VOID
LibNbSetDefaultIndexes (
IN AMD_NB_CONFIG *NbConfigPtr
)
{
PCI_ADDR PciAddress;
PORT PortId;
LibNbPciRMW (NbConfigPtr->NbPciAddress.AddressValue | NB_HTIU_INDEX, AccessWidth32, 0x0, 0x0, NbConfigPtr);
LibNbPciRMW (NbConfigPtr->NbPciAddress.AddressValue | NB_MISC_INDEX, AccessWidth32, 0x0, 0x0, NbConfigPtr);
LibNbPciRMW (NbConfigPtr->NbPciAddress.AddressValue | NB_BIF_INDEX, AccessWidth32, 0x0, SB_CORE, NbConfigPtr);
PciAddress.AddressValue = NbConfigPtr->NbPciAddress.AddressValue;
for (PortId = MIN_PORT_ID; PortId <= MAX_PORT_ID; PortId++) {
PciAddress.Address.Device = PortId;
LibNbPciRMW (PciAddress.AddressValue | NB_BIF_INDEX, AccessWidth32, 0x0, 0x0, NbConfigPtr);
}
}