AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / HT / NbCommon / htNbOptimization.c
diff --git a/src/vendorcode/amd/agesa/f15/Proc/HT/NbCommon/htNbOptimization.c b/src/vendorcode/amd/agesa/f15/Proc/HT/NbCommon/htNbOptimization.c
new file mode 100644 (file)
index 0000000..26aa038
--- /dev/null
@@ -0,0 +1,258 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Link optimization support.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project:      AGESA
+ * @e sub-project:  HyperTransport
+ * @e \$Revision: 56279 $   @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 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 "Topology.h"
+#include "htFeat.h"
+#include "IdsHt.h"
+#include "htInterface.h"
+#include "htInterfaceGeneral.h"
+#include "htNotify.h"
+#include "htNb.h"
+#include "htNbCommonHardware.h"
+#include "htNbOptimization.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_HT_NBCOMMON_HTNBOPTIMIZATION_FILECODE
+/*----------------------------------------------------------------------------
+ *                          DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/***************************************************************************
+ ***                            Link Optimization                        ***
+ ***************************************************************************/
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Get Link features into system data structure.
+ *
+ * @HtNbMethod{::F_GATHER_LINK_FEATURES}
+ *
+ * For a specific discovered CPU Link, populate the port list with the frequency
+ * capabilities.  Support for other link oriented capabilities, currently:
+ * - Unit ID Clumping. Set to disabled. This doesn't mean the CPU doesn't support clumping,
+ *   it just means:
+ *   - The CPU doesn't clump its host unit ids, and
+ *   - We don't have to check as carefully in SetLinkData whether the port is an IO host link.
+ *
+ * @param[in,out] ThisPort         The PortList structure entry for this link's port
+ * @param[in]     Interface        Access to non-HT support functions.
+ * @param[in]     PlatformConfig   Platform profile/build option config structure.
+ * @param[in]     Nb               this northbridge
+ */
+VOID
+GatherLinkFeatures (
+  IN OUT   PORT_DESCRIPTOR        *ThisPort,
+  IN       HT_INTERFACE           *Interface,
+  IN       PLATFORM_CONFIGURATION *PlatformConfig,
+  IN       NORTHBRIDGE            *Nb
+  )
+{
+  PCI_ADDR Reg;
+  UINT32 Frequency;
+  UINT32 ExtendedFrequency;
+
+  Reg = ThisPort->Pointer;
+  Reg.Address.Register += HTHOST_FREQ_REV_REG;
+  LibAmdPciReadBits (Reg, 30, 16, &Frequency, Nb->ConfigHandle);
+  Reg = ThisPort->Pointer;
+  Reg.Address.Register += HTHOST_FREQ_EXTENSION;
+  LibAmdPciReadBits (Reg, 15, 1, &ExtendedFrequency, Nb->ConfigHandle);
+  ThisPort->PrvFrequencyCap = ((Frequency | (ExtendedFrequency << HT_FREQUENCY_2800M)) &
+                               Nb->NorthBridgeFreqMask (ThisPort->NodeID, Interface, PlatformConfig, Nb));
+  // Check for Internal link restriction not to run at 1000 MHz (but allow lower)
+  if (IsPackageLinkInternal (Nb->GetPackageLink (ThisPort->NodeID, ThisPort->Link, Nb))) {
+    ThisPort->PrvFrequencyCap &= ~(HT_FREQUENCY_LIMIT_1000M & ~HT_FREQUENCY_LIMIT_800M);
+  }
+  ThisPort->ClumpingSupport = HT_CLUMPING_DISABLE;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Change the hardware state for all Links according to the now optimized data in the
+ * port list data structure for link reganging.
+ *
+ * @HtNbMethod{::F_SET_LINK_REGANG}
+ *
+ * @param[in]     Node   the node on which to regang a link
+ * @param[in]     Link   the sublink 0 of the sublink pair to regang
+ * @param[in]     Nb     this northbridge
+ */
+VOID
+SetLinkRegang (
+  IN       UINT8       Node,
+  IN       UINT8       Link,
+  IN       NORTHBRIDGE *Nb
+  )
+{
+  PCI_ADDR Reg;
+  UINT32 Temp;
+
+  Temp = 1;
+  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+                                 MakePciBusFromNode (Node),
+                                 MakePciDeviceFromNode (Node),
+                                 CPU_HTNB_FUNC_00,
+                                 REG_HT_LINK_EXT_CONTROL0_0X170 + (4 * Link));
+
+  LibAmdPciWriteBits (Reg, 0, 0, &Temp, Nb->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Change the hardware state for all Links according to the now optimized data in the
+ * port list data structure  for Unit Id Clumping.
+ *
+ * @HtNbMethod{::F_SET_LINK_UNITID_CLUMPING}
+ *
+ * This applies to the host root of a non-coherent chain.
+ *
+ * @param[in]     Node              the node on which to enable clumping
+ * @param[in]     Link              the link for which to enable clumping
+ * @param[in]     ClumpingEnables   the unit id clumping enables
+ * @param[in]     Nb                this northbridge
+ */
+VOID
+SetLinkUnitIdClumping (
+  IN       UINT8       Node,
+  IN       UINT8       Link,
+  IN       UINT32      ClumpingEnables,
+  IN       NORTHBRIDGE *Nb
+  )
+{
+  PCI_ADDR Reg;
+
+  // Host Unit Ids are not clumped.
+  ASSERT ((ClumpingEnables & 0x3) == 0);
+
+  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+                                 MakePciBusFromNode (Node),
+                                 MakePciDeviceFromNode (Node),
+                                 CPU_HTNB_FUNC_00,
+                                 REG_HT_LINK_CLUMPING0_0X110 + (4 * Link));
+
+  LibAmdPciWriteBits (Reg, 31, 0, &ClumpingEnables, Nb->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Change the hardware state for all Links according to the now optimized data in the
+ * port list data structure for link frequency.
+ *
+ * @HtNbMethod{::F_SET_LINK_FREQUENCY}
+ *
+ * Handle extended frequencies.  For HT3 frequencies, ensure Retry and Scrambling are
+ * set. For HT1, clear them.
+ *
+ * @param[in]     Node        the node on which to set frequency for a link
+ * @param[in]     Link        the link to set frequency
+ * @param[in]     Frequency   the frequency to set
+ * @param[in]     Nb          this northbridge
+ */
+VOID
+SetLinkFrequency (
+  IN       UINT8          Node,
+  IN       UINT8          Link,
+  IN       UINT8          Frequency,
+  IN       NORTHBRIDGE    *Nb
+  )
+{
+  UINT32 Temp;
+  PCI_ADDR Reg;
+
+  ASSERT ((Frequency >= HT_FREQUENCY_600M && Frequency <= HT_FREQUENCY_3200M)
+          || (Frequency == HT_FREQUENCY_200M) || (Frequency == HT_FREQUENCY_400M));
+
+  // Handle extended frequencies, 2800 MHz and above.  31 > Frequency > 16 in this case.
+  if (Frequency > HT_FREQUENCY_2600M) {
+    Temp = 1;
+  } else {
+    // Clear it if not extended.
+    Temp = 0;
+  }
+  Reg = Nb->MakeLinkBase (Node, Link, Nb);
+  Reg.Address.Register += HTHOST_FREQ_EXTENSION;
+  LibAmdPciWriteBits (Reg, 0, 0, &Temp, Nb->ConfigHandle);
+  Reg = Nb->MakeLinkBase (Node, Link, Nb);
+  Reg.Address.Register += HTHOST_FREQ_REV_REG;
+  Temp = (Frequency & 0x0F);
+  LibAmdPciWriteBits (Reg, 11, 8, &Temp, Nb->ConfigHandle);
+  //  Gen1 = 200Mhz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz
+  if (Frequency > HT_FREQUENCY_1000M) {
+    // Enable  for Gen3 frequencies
+    Temp = 1;
+  } else {
+    // Disable  for Gen1 frequencies
+    Temp = 0;
+  }
+  // HT3 retry mode enable / disable
+  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+                                 MakePciBusFromNode (Node),
+                                 MakePciDeviceFromNode (Node),
+                                 CPU_HTNB_FUNC_00,
+                                 REG_HT_LINK_RETRY0_0X130 + (4 * Link));
+  LibAmdPciWriteBits (Reg, 0, 0, &Temp, Nb->ConfigHandle);
+  // and Scrambling enable / disable
+  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+                                 MakePciBusFromNode (Node),
+                                 MakePciDeviceFromNode (Node),
+                                 CPU_HTNB_FUNC_00,
+                                 REG_HT_LINK_EXT_CONTROL0_0X170 + (4 * Link));
+  LibAmdPciWriteBits (Reg, 3, 3, &Temp, Nb->ConfigHandle);
+}