AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / Family / 0x15 / OR / F15OrL3Features.c
diff --git a/src/vendorcode/amd/agesa/f15/Proc/CPU/Family/0x15/OR/F15OrL3Features.c b/src/vendorcode/amd/agesa/f15/Proc/CPU/Family/0x15/OR/F15OrL3Features.c
new file mode 100644 (file)
index 0000000..1c3b0bd
--- /dev/null
@@ -0,0 +1,549 @@
+/* $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,
+};