blob: 8a5c5dba967d9b5f5dfca0e5a1c712bfaa0c0b8d [file] [log] [blame]
/**
* @file
*
* NB Initialization.
*
* Init IOAPIC/IOMMU/Misc NB features.
*
* @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"
/*----------------------------------------------------------------------------------------
* 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
*----------------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------------------*/
/**
* Early post validate input parameters
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
AGESA_STATUS
NbLibEarlyPostInitValidateInput (
IN AMD_NB_CONFIG *pConfig
)
{
AGESA_STATUS Status;
NB_CONFIG *pNbConfig;
NB_INFO NbInfo;
Status = AGESA_SUCCESS;
NbInfo = LibNbGetRevisionInfo (pConfig);
if (NbInfo.Type == NB_UNKNOWN) {
return AGESA_FATAL;
}
pNbConfig = GET_NB_CONFIG_PTR (pConfig);
if (pNbConfig->sHeader.InitializerID != INITIALIZED_BY_INITIALIZER) {
Status = NbLibInitializer (pConfig);
}
if (pNbConfig->SysMemoryTomBelow4G == 0) {
Status = AGESA_FATAL;
}
//pNbConfig->sHeader.InitializerID = PH_AmdEarlyPostInit;
return Status;
}
/*----------------------------------------------------------------------------------------*/
/**
* Mid/Late post validate input parameters
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
AGESA_STATUS
NbLibPostInitValidateInput (
IN AMD_NB_CONFIG *pConfig
)
{
AGESA_STATUS Status;
NB_CONFIG *pNbConfig;
NB_INFO NbInfo;
NbInfo = LibNbGetRevisionInfo (pConfig);
Status = AGESA_SUCCESS;
if (NbInfo.Type == NB_UNKNOWN) {
return AGESA_FATAL;
}
pNbConfig = GET_NB_CONFIG_PTR (pConfig);
if (pNbConfig->sHeader.InitializerID != INITIALIZED_BY_INITIALIZER) {
Status = AGESA_FATAL;
}
//pNbConfig = GET_NB_CONFIG_PTR (pConfig);
//if (pNbConfig->sHeader.InitializerID != PH_AmdEarlyPostInit) {
// return AGESA_FATAL;
//}
return Status;
}
/*----------------------------------------------------------------------------------------*/
/**
* Prepare NB to boot to OS.
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
AGESA_STATUS
NbLibPrepareToOS (
IN AMD_NB_CONFIG *pConfig
)
{
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG00, AccessS3SaveWidth32, 0xffffffff, BIT7, pConfig);
return AGESA_SUCCESS;
}
/*----------------------------------------------------------------------------------------*/
/**
* Set Multiple NB support
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
VOID
NbMultiNbIocInit (
IN AMD_NB_CONFIG *pConfig
)
{
UINT32 Value;
NB_CONFIG *pNbConfig;
pNbConfig = GET_NB_CONFIG_PTR (pConfig);
if (GET_BLOCK_CONFIG_PTR (pConfig)->NumberOfNorthbridges > 0) {
if (pConfig->NbPciAddress.AddressValue == 0) {
//Primary NB
Value = BIT3 + (HT_INTERRUPT_ENCODING_OFFSET << 4);
} else {
//Secondary NB
Value = BIT2 + (HT_INTERRUPT_ENCODING_OFFSET << 4);
}
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG75, AccessS3SaveWidth32, (UINT32)~((0x7f << 2) + BIT28) , Value, pConfig);
}
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG75, AccessS3SaveWidth32, (UINT32)~(BIT9 + BIT10 + BIT28), pNbConfig->P2PMode << 9, pConfig);
}
/*----------------------------------------------------------------------------------------*/
/**
* Set NB SSID/SVID.
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
VOID
NbLibSetSSID (
IN AMD_NB_CONFIG *pConfig
)
{
NB_CONFIG *pNbConfig;
pNbConfig = GET_NB_CONFIG_PTR (pConfig);
if (pNbConfig->SSID == 0xffffffff) {
LibNbPciRead (pConfig->NbPciAddress.AddressValue, AccessWidth32, &pNbConfig->SSID, pConfig);
}
if (pNbConfig->SSID != 0) {
LibNbPciWrite (pConfig->NbPciAddress.AddressValue | NB_PCI_REG50, AccessS3SaveWidth32, &pNbConfig->SSID, pConfig);
}
}
/*----------------------------------------------------------------------------------------*/
/**
* Setup UnitId clamping
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
VOID
NbLibSetupClumping (
IN AMD_NB_CONFIG *pConfig
)
{
UINT16 ClumpingCapability;
UINT16 Value;
NB_CONFIG *pNbConfig;
pNbConfig = GET_NB_CONFIG_PTR (pConfig);
Value = 0;
if (LibNbGetCpuFamily () == CPU_FAMILY_NPT) {
return;
}
LibNbPciRead (pConfig->NbPciAddress.AddressValue | NB_PCI_REG58, AccessS3SaveWidth16, &ClumpingCapability, pConfig);
if ((ClumpingCapability & BIT3) != 0 &&
(pNbConfig->UnitIdClumping & DEV3_CLUMPING) != 0 &&
!LibNbIsDevicePresent (PcieLibGetPortPciAddress (3, pConfig), pConfig)) {
Value |= BIT3;
}
if ((ClumpingCapability & BIT12) != 0 &&
(pNbConfig->UnitIdClumping & DEV12_CLUMPING) != 0 &&
!LibNbIsDevicePresent (PcieLibGetPortPciAddress (12, pConfig), pConfig)) {
Value |= BIT12;
}
if (Value != 0) {
LibNbPciRMW (pConfig->NbPciAddress.AddressValue | NB_PCI_REG5C, AccessS3SaveWidth16, 0xffff, Value, pConfig);
LibNbPciRMW (MAKE_SBDFO (0, 0, pConfig->NbHtPath.NodeID + 0x18, 0, HT_PATH_LINK_ID (pConfig->NbHtPath) * 4 + HT_PATH_SUBLINK_ID (pConfig->NbHtPath) * 0x10 + 0x110), AccessS3SaveWidth16, 0xffff, Value, pConfig);
}
}
/*----------------------------------------------------------------------------------------*/
/**
* Set top of memory in NB.
* NB will not pass to CPU any upstream DMA request to address above TOM and TOM2
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
AGESA_STATUS
NbLibSetTopOfMemory (
IN AMD_NB_CONFIG *pConfig
)
{
NB_CONFIG *pNbConfig;
UINT32 RD890_TOM2;
UINT32 RD890_TOM3;
RD890_TOM2 = 0;
RD890_TOM3 = 0;
pNbConfig = GET_NB_CONFIG_PTR (pConfig);
if (pNbConfig->SysMemoryTomBelow4G != 0) {
LibNbPciRMW (pConfig->NbPciAddress.AddressValue | NB_PCI_REG90, AccessS3SaveWidth32, 0, ((UINT32)pNbConfig->SysMemoryTomBelow4G) << 20, pConfig);
}
if (pNbConfig->SysMemoryTomAbove4G != 0) {
if ((pNbConfig->SysMemoryTomAbove4G - 1) <= 0xfffff) {
RD890_TOM2 = pNbConfig->SysMemoryTomAbove4G;
} else {
RD890_TOM2 = (UINT32) (0xFD00000000 >> 20);
RD890_TOM3 = pNbConfig->SysMemoryTomAbove4G;
}
}
if (RD890_TOM2 != 0) {
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG31, AccessS3SaveWidth32, 0, (RD890_TOM2 >> 12), pConfig);
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_HTIU_INDEX, NB_HTIU_REG30, AccessS3SaveWidth32, 0, (RD890_TOM2 << 20) | 1, pConfig);
}
if (RD890_TOM3 != 0) {
LibNbPciIndexRMW (pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX, NB_MISC_REG4E, AccessS3SaveWidth32, 0, ((UINT32)pNbConfig->SysMemoryTomAbove4G >> 2) | BIT31, pConfig);
}
return AGESA_SUCCESS;
}
/*----------------------------------------------------------------------------------------*/
/**
* Loget COre APic ID and dtore to scratch
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
AGESA_STATUS
NbLibGetCore0ApicId (
IN AMD_NB_CONFIG *pConfig
)
{
UINT64 Value;
UINT32 Apic20;
NB_CONFIG *pNbConfig;
pNbConfig = GET_NB_CONFIG_PTR (pConfig);
LibAmdMsrRead (0x0000001B, &Value, (AMD_CONFIG_PARAMS *)pConfig);
LibNbMemRead ((Value & 0xfffffffff000) + 0x20, AccessWidth32, &Apic20, pConfig);
pNbConfig->Reserved = (UINT16) (Apic20 >> 24);
return AGESA_SUCCESS;
}
/*----------------------------------------------------------------------------------------*/
/**
* Direct NMI message to Core 0
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
VOID
NbLibSetNmiRouting (
IN AMD_NB_CONFIG *pConfig
)
{
NB_CONFIG *pNbConfig;
pNbConfig = GET_NB_CONFIG_PTR (pConfig);
LibNbPciIndexRMW (
pConfig->NbPciAddress.AddressValue | NB_MISC_INDEX,
NB_MISC_REG12,
AccessS3SaveWidth32,
0x00ffffff,
(UINT32)pNbConfig->Reserved << 24,
pConfig);
}
/*----------------------------------------------------------------------------------------*/
/**
* AMD structures initializer for all NB.
*
*
*
* @param[in] ConfigPtr Northbridges configuration block pointer.
*
*/
AGESA_STATUS
AmdNbInitializer (
IN OUT AMD_NB_CONFIG_BLOCK *ConfigPtr
)
{
AGESA_STATUS Status;
Status = LibNbApiCall (NbLibInitializer, ConfigPtr);
return Status;
}
/*----------------------------------------------------------------------------------------*/
/**
* NB config structure initializer
*
*
*
* @param[in] pConfig Northbridge configuration structure pointer.
*
*/
/*----------------------------------------------------------------------------------------*/
AGESA_STATUS
NbLibInitializer (
IN OUT AMD_NB_CONFIG *pConfig
)
{
UINT64 Value64;
NB_CONFIG *pNbConfig;
pNbConfig = GET_NB_CONFIG_PTR (pConfig);
if (pNbConfig == NULL) {
return AGESA_WARNING;
}
if (pNbConfig->sHeader.InitializerID == INITIALIZED_BY_INITIALIZER) {
return AGESA_SUCCESS;
}
LibAmdMemFill (pNbConfig, 0, sizeof (NB_CONFIG), (AMD_CONFIG_PARAMS *)&(pNbConfig->sHeader));
pNbConfig->sHeader.InitializerID = INITIALIZED_BY_INITIALIZER;
// Get TOM and TOM2
LibAmdMsrRead (0xC001001a, &Value64, (AMD_CONFIG_PARAMS *)pConfig);
pNbConfig->SysMemoryTomBelow4G = (UINT16) (Value64 >> 20);
LibAmdMsrRead (0xC0010010, &Value64, (AMD_CONFIG_PARAMS *)pConfig);
if ((Value64 & BIT21) != 0) {
LibAmdMsrRead (0xC001001d, &Value64, (AMD_CONFIG_PARAMS *)pConfig);
pNbConfig->SysMemoryTomAbove4G = (UINT32) (Value64 >> 20);
}
pNbConfig->P2PMode = 1;
pNbConfig->UnitIdClumping = 3;
return AGESA_SUCCESS;
}