AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / HT / Features / htFeatGanging.c
diff --git a/src/vendorcode/amd/agesa/f15/Proc/HT/Features/htFeatGanging.c b/src/vendorcode/amd/agesa/f15/Proc/HT/Features/htFeatGanging.c
new file mode 100644 (file)
index 0000000..533d376
--- /dev/null
@@ -0,0 +1,218 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Routines for re-ganging Links.
+ *
+ * Implement the reganging feature.
+ *
+ * @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 "htInterface.h"
+#include "htNb.h"
+#include "htFeatGanging.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G2_PEI)
+
+#define FILECODE PROC_HT_FEATURES_HTFEATGANGING_FILECODE
+/*----------------------------------------------------------------------------
+ *                          DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ *                           TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ *                        PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ *                            EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ *                              LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/***************************************************************************
+ ***                            Link Optimization                        ***
+ ***************************************************************************/
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Test the subLinks of a Link to see if they qualify to be reganged.
+ *
+ * @HtFeatMethod{::F_REGANG_LINKS}
+ *
+ * If they do, update the port list data to indicate that this should be done.
+ * @note  no actual hardware state is changed in this routine.
+ *
+ * @param[in,out] State          Our global state
+ */
+VOID
+RegangLinks (
+  IN OUT   STATE_DATA *State
+  )
+{
+  FINAL_LINK_STATE FinalLinkState;
+  UINT8 i;
+  UINT8 j;
+  for (i = 0; i < (State->TotalLinks * 2); i += 2) {
+    // Data validation
+    ASSERT ((*State->PortList)[i].Type < 2 && (*State->PortList)[i].Link < State->Nb->MaxLinks);
+    ASSERT ((*State->PortList)[i + 1].Type < 2 && (*State->PortList)[i + 1].Link < State->Nb->MaxLinks);
+
+    // Regang is false unless we pass all conditions below
+    (*State->PortList)[i].SelRegang = FALSE;
+    (*State->PortList)[i + 1].SelRegang = FALSE;
+
+    // Only process cpu to cpu Links
+    if ( ((*State->PortList)[i].Type != PORTLIST_TYPE_CPU) ||
+         ((*State->PortList)[i + 1].Type != PORTLIST_TYPE_CPU)) {
+      continue;
+    }
+
+    for (j = i + 2; j < State->TotalLinks*2; j += 2) {
+      // Only process cpu to cpu Links
+      if ( ((*State->PortList)[j].Type != PORTLIST_TYPE_CPU) ||
+           ((*State->PortList)[j + 1].Type != PORTLIST_TYPE_CPU) ) {
+        continue;
+      }
+
+      // Links must be from the same source
+      if ((*State->PortList)[i].NodeID != (*State->PortList)[j].NodeID) {
+        continue;
+      }
+
+      // Link must be to the same target
+      if ((*State->PortList)[i + 1].NodeID != (*State->PortList)[j + 1].NodeID) {
+        continue;
+      }
+
+      // Ensure same source base port
+      if (((*State->PortList)[i].Link & 3) != ((*State->PortList)[j].Link & 3)) {
+        continue;
+      }
+
+      // Ensure same destination base port
+      if (((*State->PortList)[i + 1].Link & 3) != ((*State->PortList)[j + 1].Link & 3)) {
+        continue;
+      }
+
+      // Ensure subLink0 routes to subLink0
+      if (((*State->PortList)[i].Link & 4) != ((*State->PortList)[i + 1].Link & 4)) {
+        continue;
+      }
+
+      // (therefore subLink1 routes to subLink1)
+      ASSERT (((*State->PortList)[j].Link & 4) == ((*State->PortList)[j + 1].Link & 4));
+
+      FinalLinkState = State->HtInterface->GetSkipRegang ((*State->PortList)[i].NodeID,
+                                         (*State->PortList)[i].Link & 0x03,
+                                         (*State->PortList)[i + 1].NodeID,
+                                         (*State->PortList)[i + 1].Link & 0x03,
+                                         State);
+      if (FinalLinkState == MATCHED) {
+        continue;
+      } else if (FinalLinkState == POWERED_OFF) {
+        // StopLink will be done on the sublink 1, thus OR in 4 to the link to ensure it.
+        State->Nb->StopLink ((*State->PortList)[i].NodeID, ((*State->PortList)[i].Link | 4), State, State->Nb);
+        State->Nb->StopLink ((*State->PortList)[i + 1].NodeID, ((*State->PortList)[i + 1].Link | 4), State, State->Nb);
+      }
+
+      //
+      // Create a ganged portlist entry for the two regang-able subLinks.
+      //
+      // All info will be that of subLink zero.
+      // (If Link discovery order was other than ascending, fix the .Pointer field too.)
+      //
+      //
+      if (((*State->PortList)[i].Link & 4) != 0) {
+        (*State->PortList)[i].Pointer = (*State->PortList)[j].Pointer;
+        (*State->PortList)[i + 1].Pointer = (*State->PortList)[j + 1].Pointer;
+      }
+      (*State->PortList)[i].Link &= 0x03;                       // Force to point to subLink0
+      (*State->PortList)[i + 1].Link &= 0x03;
+      // If powered off, sublink 1 is removed but the link is still 8 bits.
+      if (FinalLinkState != POWERED_OFF) {
+        (*State->PortList)[i].SelRegang = TRUE;                   // Enable Link reganging
+        (*State->PortList)[i + 1].SelRegang = TRUE;
+        (*State->PortList)[i].PrvWidthOutCap = HT_WIDTH_16_BITS;
+        (*State->PortList)[i + 1].PrvWidthOutCap = HT_WIDTH_16_BITS;
+        (*State->PortList)[i].PrvWidthInCap = HT_WIDTH_16_BITS;
+        (*State->PortList)[i + 1].PrvWidthInCap = HT_WIDTH_16_BITS;
+      }
+
+      // Delete PortList[j, j + 1], slow but easy to debug implementation
+      State->TotalLinks--;
+      LibAmdMemCopy (&((*State->PortList)[j]),
+                     &((*State->PortList)[j + 2]),
+                     sizeof (PORT_DESCRIPTOR)*(State->TotalLinks* 2 - j),
+                     State->ConfigHandle);
+      LibAmdMemFill (&((*State->PortList)[State->TotalLinks * 2]), INVALID_LINK, (sizeof (PORT_DESCRIPTOR) * 2), State->ConfigHandle);
+
+      break; // Exit loop, advance to PortList[i + 2]
+    }
+  }
+}