summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.c')
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.c b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.c
new file mode 100644
index 0000000000..4c4d6568e2
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.c
@@ -0,0 +1,232 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * SubLink management Routines.
+ *
+ * Contains routines for subLink frequency ratios.
+ *
+ * @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 "Ids.h"
+#include "amdlib.h"
+#include "Topology.h"
+#include "htFeat.h"
+#include "IdsHt.h"
+#include "htFeatSublinks.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_HT_FEATURES_HTFEATSUBLINKS_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+typedef struct {
+ UINT8 HiFreq;
+ UINT8 LoFreq;
+} VALID_RATIO_ITEM;
+
+STATIC CONST VALID_RATIO_ITEM ROMDATA ValidRatioList[] =
+{
+ {HT_FREQUENCY_3200M, HT_FREQUENCY_1600M}, // 3200MHz / 1600MHz 2:1
+ {HT_FREQUENCY_3200M, HT_FREQUENCY_800M}, // 3200MHz / 800MHz 4:1
+ {HT_FREQUENCY_3200M, HT_FREQUENCY_400M}, // 3200MHz / 400MHz 8:1
+ {HT_FREQUENCY_2800M, HT_FREQUENCY_1400M}, // 2800MHz / 1400MHz 2:1
+ {HT_FREQUENCY_2400M, HT_FREQUENCY_1200M}, // 2400MHz / 1200MHz 2:1
+ {HT_FREQUENCY_2400M, HT_FREQUENCY_600M}, // 2400MHz / 600MHz 4:1
+ {HT_FREQUENCY_2400M, HT_FREQUENCY_400M}, // 2400MHz / 400MHz 6:1
+ {HT_FREQUENCY_2000M, HT_FREQUENCY_1000M}, // 2000MHz / 1000MHz 2:1
+ {HT_FREQUENCY_1600M, HT_FREQUENCY_800M}, // 1600MHz / 800MHz 2:1
+ {HT_FREQUENCY_1600M, HT_FREQUENCY_400M}, // 1600MHz / 400MHz 4:1
+ {HT_FREQUENCY_1600M, HT_FREQUENCY_200M}, // 1600MHz / 200Mhz 8:1
+ {HT_FREQUENCY_1200M, HT_FREQUENCY_600M}, // 1200MHz / 600MHz 2:1
+ {HT_FREQUENCY_1200M, HT_FREQUENCY_200M}, // 1200MHz / 200MHz 6:1
+ {HT_FREQUENCY_800M, HT_FREQUENCY_400M}, // 800MHz / 400MHz 2:1
+ {HT_FREQUENCY_800M, HT_FREQUENCY_200M}, // 800MHz / 200MHz 4:1
+ {HT_FREQUENCY_400M, HT_FREQUENCY_200M} // 400MHz / 200MHz 2:1
+};
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/***************************************************************************
+ *** Link Optimization ***
+ ***************************************************************************/
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Iterate through all Links, checking the frequency of each subLink pair.
+ *
+ * @HtFeatMethod{::F_SUBLINK_RATIO_FIXUP}
+ *
+ * Make the adjustment to the port list data so that the frequencies
+ * are at a valid ratio, reducing frequency as needed to achieve
+ * this. (All Links support the minimum 200 MHz frequency.) Repeat
+ * the above until no adjustments are needed.
+ * @note no hardware state changes in this routine.
+ *
+ * @param[in,out] State Link state and port list
+ *
+ */
+VOID
+SubLinkRatioFixup (
+ IN OUT STATE_DATA *State
+ )
+{
+ UINT8 i;
+ UINT8 j;
+ UINT8 ValidRatioItem;
+ BOOLEAN Changes;
+ BOOLEAN Downgrade;
+ UINT8 HiIndex;
+ UINT8 HiFreq;
+ UINT8 LoFreq;
+
+ UINT32 Temp;
+
+ do {
+ Changes = FALSE;
+ for (i = 0; i < State->TotalLinks*2; i++) {
+ // Must be a CPU Link
+ if ((*State->PortList)[i].Type != PORTLIST_TYPE_CPU) {
+ continue;
+ }
+ // Only look for subLink1's
+ if ((*State->PortList)[i].Link < 4) {
+ continue;
+ }
+
+ for (j = 0; j < State->TotalLinks*2; j++) {
+ // Step 1. Find the matching subLink0
+ if ((*State->PortList)[j].Type != PORTLIST_TYPE_CPU) {
+ continue;
+ }
+ if ((*State->PortList)[j].NodeID != (*State->PortList)[i].NodeID) {
+ continue;
+ }
+ if ((*State->PortList)[j].Link != ((*State->PortList)[i].Link & 0x03)) {
+ continue;
+ }
+
+ // Step 2. Check for an illegal frequency ratio
+ if ((*State->PortList)[i].SelFrequency >= (*State->PortList)[j].SelFrequency) {
+ HiIndex = i;
+ HiFreq = (*State->PortList)[i].SelFrequency;
+ LoFreq = (*State->PortList)[j].SelFrequency;
+ } else {
+ HiIndex = j;
+ HiFreq = (*State->PortList)[j].SelFrequency;
+ LoFreq = (*State->PortList)[i].SelFrequency;
+ }
+
+ // The frequencies are 1:1, no need to do anything
+ if (HiFreq == LoFreq) {
+ break;
+ }
+
+ Downgrade = TRUE;
+
+ for (ValidRatioItem = 0; ValidRatioItem < (sizeof (ValidRatioList) / sizeof (VALID_RATIO_ITEM)); ValidRatioItem++) {
+ if ((HiFreq == ValidRatioList[ValidRatioItem].HiFreq) &&
+ (LoFreq == ValidRatioList[ValidRatioItem].LoFreq)) {
+ Downgrade = FALSE;
+ break;
+ }
+ }
+
+ // Step 3. Downgrade the higher of the two frequencies, and set Changes to FALSE
+ if (Downgrade) {
+ // Although the problem was with the port specified by hiIndex, we need to
+ // Downgrade both ends of the Link.
+ HiIndex = HiIndex & 0xFE; // Select the 'upstream' (i.e. even) port
+
+ Temp = (*State->PortList)[HiIndex].CompositeFrequencyCap;
+
+ // Remove HiFreq from the list of valid frequencies
+ Temp = Temp & ~((UINT32)1 << HiFreq);
+ ASSERT (Temp != 0);
+ (*State->PortList)[HiIndex].CompositeFrequencyCap = (UINT32)Temp;
+ (*State->PortList)[HiIndex + 1].CompositeFrequencyCap = (UINT32)Temp;
+
+ HiFreq = LibAmdBitScanReverse (Temp);
+
+ (*State->PortList)[HiIndex].SelFrequency = HiFreq;
+ (*State->PortList)[HiIndex + 1].SelFrequency = HiFreq;
+
+ Changes = TRUE;
+ }
+ }
+ }
+ } while (Changes); // Repeat until a valid configuration is reached
+}