summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.c')
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.c b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.c
new file mode 100644
index 0000000000..0b0a745ff2
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.c
@@ -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: 35136 $ @e \$Date: 2010-07-16 11:29:48 +0800 (Fri, 16 Jul 2010) $
+ *
+ */
+/*
+ *****************************************************************************
+ *
+ * Copyright (c) 2011, 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 (G1_PEICC)
+
+#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]
+ }
+ }
+}