blob: 1c3b0bd100c28babd4dbea091d7e9a06c19e7591 [file] [log] [blame]
/* $NoKeywords:$ */
/**
* @file
*
* AMD Family_15 Orochi L3 dependent feature support functions.
*
* Provides the functions necessary to initialize L3 dependent features.
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: AGESA
* @e sub-project: CPU/Family/0x15/OR
* @e \$Revision: 60552 $ @e \$Date: 2011-10-17 18:50:55 -0600 (Mon, 17 Oct 2011) $
*
*/
/*
******************************************************************************
*
* 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.
*
******************************************************************************
*/
/*
*----------------------------------------------------------------------------
* MODULES USED
*
*----------------------------------------------------------------------------
*/
#include "AGESA.h"
#include "amdlib.h"
#include "Ids.h"
#include "CommonReturns.h"
#include "cpuRegisters.h"
#include "cpuF15PowerMgmt.h"
#include "cpuF15OrPowerMgmt.h"
#include "cpuLateInit.h"
#include "cpuServices.h"
#include "GeneralServices.h"
#include "cpuFamilyTranslation.h"
#include "cpuL3Features.h"
#include "Filecode.h"
CODE_GROUP (G3_DXE)
RDATA_GROUP (G3_DXE)
#define FILECODE PROC_CPU_FAMILY_0X15_OR_F15ORL3FEATURES_FILECODE
/*----------------------------------------------------------------------------
* DEFINITIONS AND MACROS
*
*----------------------------------------------------------------------------
*/
#define L3Cache8_0M 0xCCCC
/*----------------------------------------------------------------------------
* TYPEDEFS AND STRUCTURES
*
*----------------------------------------------------------------------------
*/
/**
* The family 15h background scrubber context structure.
*
* These fields need to be saved, modified, then restored
* per die as part of HT Assist initialization.
*/
typedef struct {
UINT32 DramScrub:5; ///< DRAM scrub rate
UINT32 :3; ///< Reserved
UINT32 L3Scrub:5; ///< L3 scrub rate
UINT32 :3; ///< Reserved
UINT32 Redirect:1; ///< DRAM scrubber redirect enable
UINT32 :15; ///< Reserved
} F15_SCRUB_CONTEXT;
/*----------------------------------------------------------------------------
* PROTOTYPES OF LOCAL FUNCTIONS
*
*----------------------------------------------------------------------------
*/
BOOLEAN
F15OrIsNonOptimalConfig (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN UINT32 Socket,
IN AMD_CONFIG_PARAMS *StdHeader
);
/*----------------------------------------------------------------------------
* EXPORTED FUNCTIONS
*
*----------------------------------------------------------------------------
*/
/*---------------------------------------------------------------------------------------*/
/**
* Check to see if the input CPU supports L3 dependent features.
*
* @param[in] L3FeatureServices L3 feature family services.
* @param[in] Socket Processor socket to check.
* @param[in] StdHeader Config Handle for library, services.
* @param[in] PlatformConfig Contains the runtime modifiable feature input data.
*
* @retval TRUE L3 dependent features are supported.
* @retval FALSE L3 dependent features are not supported.
*
*/
BOOLEAN
STATIC
F15OrIsL3FeatureSupported (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN UINT32 Socket,
IN AMD_CONFIG_PARAMS *StdHeader,
IN PLATFORM_CONFIGURATION *PlatformConfig
)
{
UINT32 Module;
UINT32 LocalPciRegister;
BOOLEAN IsSupported;
PCI_ADDR PciAddress;
AGESA_STATUS IgnoredStatus;
IsSupported = FALSE;
for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) {
PciAddress.Address.Function = FUNC_3;
PciAddress.Address.Register = NB_CAPS_REG;
LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
if (((NB_CAPS_REGISTER *) &LocalPciRegister)->L3Capable == 1) {
IsSupported = TRUE;
}
break;
}
}
return IsSupported;
}
/*---------------------------------------------------------------------------------------*/
/**
* Enable the Probe filter feature
*
* @param[in] L3FeatureServices L3 family services.
* @param[in] Socket Processor socket to check.
* @param[in] StdHeader Config Handle for library, services.
*
*/
VOID
STATIC
F15OrHtAssistInit (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN UINT32 Socket,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT32 Module;
UINT32 L3CacheParamRegister;
UINT32 PfCtrlRegister;
PCI_ADDR PciAddress;
AGESA_STATUS IgnoredStatus;
for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) {
PciAddress.Address.Function = FUNC_3;
PciAddress.Address.Register = L3_CACHE_PARAM_REG;
LibAmdPciRead (AccessWidth32, PciAddress, &L3CacheParamRegister, StdHeader);
((L3_CACHE_PARAM_REGISTER *) &L3CacheParamRegister)->L3TagInit = 1;
LibAmdPciWrite (AccessWidth32, PciAddress, &L3CacheParamRegister, StdHeader);
do {
LibAmdPciRead (AccessWidth32, PciAddress, &L3CacheParamRegister, StdHeader);
} while (((L3_CACHE_PARAM_REGISTER *) &L3CacheParamRegister)->L3TagInit != 0);
PciAddress.Address.Register = PROBE_FILTER_CTRL_REG;
LibAmdPciRead (AccessWidth32, PciAddress, &PfCtrlRegister, StdHeader);
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFWayHashEn = 1;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFLoIndexHashEn = 1;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFWayNum = 2;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFSubCacheEn = 0xF;
if ((L3CacheParamRegister & 0xFFFF) == L3Cache8_0M) {
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFSubCacheSize0 = 1;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFSubCacheSize1 = 1;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFSubCacheSize2 = 1;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFSubCacheSize3 = 1;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFMode = 3;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFPreferredSORepl = 2;
} else {
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFSubCacheSize0 = 0;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFSubCacheSize1 = 0;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFSubCacheSize2 = 0;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFSubCacheSize3 = 0;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFMode = 2;
((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFPreferredSORepl = 0;
}
LibAmdPciWrite (AccessWidth32, PciAddress, &PfCtrlRegister, StdHeader);
do {
LibAmdPciRead (AccessWidth32, PciAddress, &PfCtrlRegister, StdHeader);
} while (((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFInitDone != 1);
IDS_OPTION_HOOK (IDS_HT_ASSIST, &PciAddress, StdHeader);
}
}
}
/*---------------------------------------------------------------------------------------*/
/**
* Enable the ATM Mode feature.
*
* @param[in] L3FeatureServices L3 feature family services.
* @param[in] Socket Processor socket to check.
* @param[in] StdHeader Config Handle for library, services.
*
*/
VOID
STATIC
F15OrAtmModeInit (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN UINT32 Socket,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT32 Module;
UINT32 LocalPciRegister;
PCI_ADDR PciAddress;
AGESA_STATUS IgnoredStatus;
for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) {
PciAddress.Address.Function = FUNC_0;
PciAddress.Address.Register = LTC_REG;
LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
((LTC_REGISTER *) &LocalPciRegister)->ATMModeEn = 1;
LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
PciAddress.Address.Function = FUNC_3;
PciAddress.Address.Register = L3_CONTROL_1_REG;
LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
((L3_CONTROL_1_REGISTER *) &LocalPciRegister)->L3ATMModeEn = 1;
LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
}
}
}
/*---------------------------------------------------------------------------------------*/
/**
* Save the current settings of the scrubbers, and disabled them.
*
* @param[in] L3FeatureServices L3 feature family services.
* @param[in] Socket Processor socket to check.
* @param[in] ScrubSettings Location to store current L3 scrubber settings.
* @param[in] StdHeader Config Handle for library, services.
*
*/
VOID
STATIC
F15OrGetL3ScrubCtrl (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN UINT32 Socket,
IN UINT32 ScrubSettings[L3_SCRUBBER_CONTEXT_ARRAY_SIZE],
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT32 Module;
UINT32 ScrubCtrl;
UINT32 ScrubAddr;
PCI_ADDR PciAddress;
AGESA_STATUS IgnoredStatus;
for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) {
ASSERT (Module < L3_SCRUBBER_CONTEXT_ARRAY_SIZE);
PciAddress.Address.Function = FUNC_3;
PciAddress.Address.Register = DRAM_SCRUB_ADDR_LOW_REG;
LibAmdPciRead (AccessWidth32, PciAddress, &ScrubAddr, StdHeader);
PciAddress.Address.Register = SCRUB_RATE_CTRL_REG;
LibAmdPciRead (AccessWidth32, PciAddress, &ScrubCtrl, StdHeader);
((F15_SCRUB_CONTEXT *) &ScrubSettings[Module])->DramScrub =
((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->DramScrub;
((F15_SCRUB_CONTEXT *) &ScrubSettings[Module])->L3Scrub =
((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->L3Scrub;
((F15_SCRUB_CONTEXT *) &ScrubSettings[Module])->Redirect =
((DRAM_SCRUB_ADDR_LOW_REGISTER *) &ScrubAddr)->ScrubReDirEn;
((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->DramScrub = 0;
((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->L3Scrub = 0;
((DRAM_SCRUB_ADDR_LOW_REGISTER *) &ScrubAddr)->ScrubReDirEn = 0;
LibAmdPciWrite (AccessWidth32, PciAddress, &ScrubCtrl, StdHeader);
PciAddress.Address.Register = DRAM_SCRUB_ADDR_LOW_REG;
LibAmdPciWrite (AccessWidth32, PciAddress, &ScrubAddr, StdHeader);
}
}
}
/*---------------------------------------------------------------------------------------*/
/**
* Restore the initial settings for the scrubbers.
*
* @param[in] L3FeatureServices L3 Feature family services.
* @param[in] Socket Processor socket to check.
* @param[in] ScrubSettings Location to store current L3 scrubber settings.
* @param[in] StdHeader Config Handle for library, services.
*
*/
VOID
STATIC
F15OrSetL3ScrubCtrl (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN UINT32 Socket,
IN UINT32 ScrubSettings[L3_SCRUBBER_CONTEXT_ARRAY_SIZE],
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT32 Module;
UINT32 LocalPciRegister;
PCI_ADDR PciAddress;
AGESA_STATUS IgnoredStatus;
for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) {
ASSERT (Module < L3_SCRUBBER_CONTEXT_ARRAY_SIZE);
PciAddress.Address.Function = FUNC_3;
PciAddress.Address.Register = SCRUB_RATE_CTRL_REG;
LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
((SCRUB_RATE_CTRL_REGISTER *) &LocalPciRegister)->DramScrub =
((F15_SCRUB_CONTEXT *) &ScrubSettings[Module])->DramScrub;
((SCRUB_RATE_CTRL_REGISTER *) &LocalPciRegister)->L3Scrub =
((F15_SCRUB_CONTEXT *) &ScrubSettings[Module])->L3Scrub;
LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
PciAddress.Address.Register = DRAM_SCRUB_ADDR_LOW_REG;
LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
((DRAM_SCRUB_ADDR_LOW_REGISTER *) &LocalPciRegister)->ScrubReDirEn =
((F15_SCRUB_CONTEXT *) &ScrubSettings[Module])->Redirect;
LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
}
}
}
/*---------------------------------------------------------------------------------------*/
/**
* Set MSR bits required for L3 feature support on each core.
*
* @param[in] L3FeatureServices L3 Feature family services.
* @param[in] HtAssistEnabled Indicates whether Ht Assist is enabled.
* @param[in] StdHeader Config Handle for library, services.
*
*/
VOID
STATIC
F15OrHookDisableCache (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN BOOLEAN HtAssistEnabled,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT64 LocalMsrRegister;
// This bit is set only if Probe Filter is enabled.
if (HtAssistEnabled) {
LibAmdMsrRead (MSR_BU_CFG2, &LocalMsrRegister, StdHeader);
LocalMsrRegister |= BIT42;
LibAmdMsrWrite (MSR_BU_CFG2, &LocalMsrRegister, StdHeader);
}
}
/*---------------------------------------------------------------------------------------*/
/**
* Check to see if the input CPU is running in the optimal configuration.
*
* @param[in] L3FeatureServices L3 Feature family services.
* @param[in] Socket Processor socket to check.
* @param[in] StdHeader Config Handle for library, services.
*
* @retval TRUE HT Assist is running sub-optimally.
* @retval FALSE HT Assist is running optimally.
*
*/
BOOLEAN
F15OrIsNonOptimalConfig (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN UINT32 Socket,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
BOOLEAN IsNonOptimal;
BOOLEAN IsMemoryPresent;
UINT32 Module;
UINT32 LocalPciRegister;
PCI_ADDR PciAddress;
AGESA_STATUS IgnoredStatus;
IsNonOptimal = FALSE;
for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) {
IsMemoryPresent = FALSE;
PciAddress.Address.Function = FUNC_2;
PciAddress.Address.Register = DRAM_CFG_HI_REG0;
LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
if (((DRAM_CFG_HI_REGISTER *) &LocalPciRegister)->MemClkFreqVal == 1) {
IsMemoryPresent = TRUE;
if (((DRAM_CFG_HI_REGISTER *) &LocalPciRegister)->MemClkFreq < 0x0a) {
IsNonOptimal = TRUE;
break;
}
}
PciAddress.Address.Register = DRAM_CFG_HI_REG1;
LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
if (((DRAM_CFG_HI_REGISTER *) &LocalPciRegister)->MemClkFreqVal == 1) {
IsMemoryPresent = TRUE;
if (((DRAM_CFG_HI_REGISTER *) &LocalPciRegister)->MemClkFreq < 0x0a) {
IsNonOptimal = TRUE;
break;
}
}
if (!IsMemoryPresent) {
IsNonOptimal = TRUE;
break;
}
}
}
return IsNonOptimal;
}
/*---------------------------------------------------------------------------------------*/
/**
* Check to see if the input CPU supports HT Assist.
*
* @param[in] L3FeatureServices L3 Feature family services.
* @param[in] PlatformConfig Contains the runtime modifiable feature input data.
* @param[in] StdHeader Config Handle for library, services.
*
* @retval TRUE HT Assist is supported.
* @retval FALSE HT Assist cannot be enabled.
*
*/
BOOLEAN
STATIC
F15OrIsHtAssistSupported (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN PLATFORM_CONFIGURATION *PlatformConfig,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
BOOLEAN IsSupported;
UINT32 CpuCount;
AP_MAILBOXES ApMailboxes;
IsSupported = FALSE;
if (PlatformConfig->PlatformProfile.UseHtAssist) {
CpuCount = GetNumberOfProcessors (StdHeader);
ASSERT (CpuCount != 0);
if (CpuCount == 1) {
GetApMailbox (&ApMailboxes.ApMailInfo.Info, StdHeader);
if (ApMailboxes.ApMailInfo.Fields.ModuleType != 0) {
IsSupported = TRUE;
}
} else if (CpuCount > 1) {
IsSupported = TRUE;
}
}
return IsSupported;
}
/*---------------------------------------------------------------------------------------*/
/**
* Check to see if the input CPU supports ATM Mode.
*
* @param[in] L3FeatureServices L3 Feature family services.
* @param[in] PlatformConfig Contains the runtime modifiable feature input data.
* @param[in] StdHeader Config Handle for library, services.
*
* @retval TRUE ATM Mode is supported.
* @retval FALSE ATM Mode cannot be enabled.
*
*/
BOOLEAN
STATIC
F15OrIsAtmModeSupported (
IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
IN PLATFORM_CONFIGURATION *PlatformConfig,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
BOOLEAN IsSupported;
IsSupported = TRUE;
if (!PlatformConfig->PlatformProfile.UseAtmMode) {
IsSupported = FALSE;
}
return IsSupported;
}
CONST L3_FEATURE_FAMILY_SERVICES ROMDATA F15OrL3Features =
{
0,
F15OrIsL3FeatureSupported,
F15OrGetL3ScrubCtrl,
F15OrSetL3ScrubCtrl,
(PF_L3_FEATURE_BEFORE_INIT) CommonVoid,
(PF_L3_FEATURE_AFTER_INIT) CommonVoid,
F15OrHookDisableCache,
(PF_L3_FEATURE_ENABLE_CACHE) CommonVoid,
F15OrIsHtAssistSupported,
F15OrHtAssistInit,
F15OrIsNonOptimalConfig,
F15OrIsAtmModeSupported,
F15OrAtmModeInit,
};