summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f14/Proc/HT/Features
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f14/Proc/HT/Features')
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatDynamicDiscovery.c783
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatDynamicDiscovery.h80
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.c218
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.h80
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatNoncoherent.c375
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatNoncoherent.h81
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatOptimization.c886
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatOptimization.h140
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatRouting.c493
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatRouting.h90
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSets.c114
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.c232
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.h80
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatTrafficDistribution.c278
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatTrafficDistribution.h79
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/Features/htIds.c153
16 files changed, 4162 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatDynamicDiscovery.c b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatDynamicDiscovery.c
new file mode 100644
index 0000000000..d6f21aa2da
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatDynamicDiscovery.c
@@ -0,0 +1,783 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Coherent Discovery Routines.
+ *
+ * Contains routines for discovery, along with Temporary routing.
+ *
+ * @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 "Topology.h"
+#include "htFeat.h"
+#include "htInterface.h"
+#include "htNotify.h"
+#include "htNb.h"
+#include "htFeatDynamicDiscovery.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_HT_FEATURES_HTFEATDYNAMICDISCOVERY_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define LOGICAL_PROCESSOR_NONE 0xFF
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/**
+ * Status result from exploring for a new node on a link.
+ */
+typedef enum {
+ ExploreNodeStatusNew, ///< A new node was discovered
+ ExploreNodeStatusGood, ///< A new link to an already known node was discovered
+ ExploreNodeStatusStop, ///< Discovery must halt now.
+ ExploreNodeStatusIgnore, ///< A new node was ignored on purpose.
+ ExploreNodeStatusMax ///< Use for bounds check and limit only
+} EXPLORE_NODE_STATUS;
+
+/**
+ * Save all the information needed about a node at its discovery.
+ *
+ * When we can access the node at a known temporary route, read everything needed
+ * to do node to socket mapping, post to ap mailbox at later times.
+ */
+typedef struct {
+ UINT8 LogicalProcessor; ///< Independent of Node,Socket group nodes into logical
+ ///< processors based on discovery.
+ UINT8 CurrentNode; ///< The node from which discovery occurred.
+ UINT8 CurrentLink; ///< The link on that node which we explored.
+ UINT8 PackageLink; ///< The package level link corresponding to CurrentLink.
+ UINT8 CurrentModuleType; ///< The current node's module type, Single or Multiple.
+ UINT8 CurrentModule; ///< This current node's module id.
+ UINT8 HardwareSocket; ///< Save the hardware socket strap (for hardware socket method).
+ UINT8 NewModuleType; ///< The new node's module type, Single or Multiple.
+ UINT8 NewModule; ///< The new node's module id.
+} NEW_NODE_SAVED_INFO_ITEM;
+
+/**
+ * A "no info" initializer for saved new node info.
+ */
+STATIC CONST NEW_NODE_SAVED_INFO_ITEM ROMDATA NoInfoSavedYet =
+{
+ LOGICAL_PROCESSOR_NONE, 0, 0, 0, 0, 0, 0, 0
+};
+
+/**
+ * A list of all the new node info, indexed by each new node's nodeid.
+ */
+typedef NEW_NODE_SAVED_INFO_ITEM (*NEW_NODE_SAVED_INFO_LIST) [MAX_NODES];
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/***************************************************************************
+ *** GENERIC HYPERTRANSPORT DISCOVERY CODE ***
+ ***************************************************************************/
+
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Ensure a request / response route from target Node to bsp.
+ *
+ * Since target Node is always a predecessor of actual target Node, each Node gets a
+ * route to actual target on the Link that goes to target. The routing produced by
+ * this routine is adequate for config access during discovery, but NOT for coherency.
+ *
+ * @param[in] TargetNode the path to actual target goes through target
+ * @param[in] ActualTarget the ultimate target being routed to
+ * @param[in] State our global state, port config info
+ *
+ */
+VOID
+STATIC
+routeFromBSP (
+ IN UINT8 TargetNode,
+ IN UINT8 ActualTarget,
+ IN STATE_DATA *State
+ )
+{
+ UINT8 PredecessorNode;
+ UINT8 PredecessorLink;
+ UINT8 CurrentPair;
+
+ if (TargetNode == 0) {
+ return; // BSP has no predecessor, stop
+ }
+
+ // Search for the Link that connects TargetNode to its predecessor
+ CurrentPair = 0;
+ while ((*State->PortList)[CurrentPair*2 + 1].NodeID != TargetNode) {
+ CurrentPair++;
+ ASSERT (CurrentPair < State->TotalLinks);
+ }
+
+ PredecessorNode = (*State->PortList)[ (CurrentPair * 2)].NodeID;
+ PredecessorLink = (*State->PortList)[ (CurrentPair * 2)].Link;
+
+ // Recursively call self to ensure the route from the BSP to the Predecessor
+ // Node is established
+ routeFromBSP (PredecessorNode, ActualTarget, State);
+
+ State->Nb->WriteRoutingTable (PredecessorNode, ActualTarget, PredecessorLink, State->Nb);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Test Compatibility of a new node, and handle failure.
+ *
+ * Make the compatibility test call for the northbridge.
+ * If the new node is incompatible, force 1P. Notify the event.
+ * Additionally, invoke the northbridge stop link method, to
+ * implement isolation of the BSP from any incompatible node.
+ *
+ * @param[in] CurrentNode The node we are exploring from
+ * @param[in] CurrentLink The Link on that node to explore.
+ * @param[in] State Access to Northbridge interface.
+ *
+ * @retval TRUE Check is Ok
+ * @retval FALSE Check failed and is handled
+ */
+BOOLEAN
+STATIC
+CheckCompatible (
+ IN UINT8 CurrentNode,
+ IN UINT8 CurrentLink,
+ IN STATE_DATA *State
+ )
+{
+ UINT8 NodeToKill;
+ BOOLEAN Result;
+
+ Result = TRUE;
+
+ // Check the northbridge of the Node we just found, to make sure it is compatible
+ // before doing anything else to it.
+ //
+ if (State->Nb->IsIllegalTypeMix ((CurrentNode + 1), State->Nb)) {
+ IDS_ERROR_TRAP;
+
+ // Notify BIOS of event
+ NotifyFatalCohProcessorTypeMix (
+ CurrentNode,
+ CurrentLink,
+ State->NodesDiscovered,
+ State
+ );
+
+ // If Node is not compatible, force boot to 1P
+ // If they are not compatible stop cHT init and:
+ // 1. Disable all cHT Links on the BSP
+ // 2. Configure the BSP routing tables as a UP.
+ // 3. Notify main BIOS.
+ //
+ State->NodesDiscovered = 0;
+ State->TotalLinks = 0;
+ // Abandon our coherent Link data structure. At this point there may
+ // be coherent Links on the BSP that are not yet in the portList, and
+ // we have to turn them off anyway. So depend on the hardware to tell us.
+ //
+ for (CurrentLink = 0; CurrentLink < State->Nb->MaxLinks; CurrentLink++) {
+ // Stop all Links which are connected, coherent, and ready
+ if (State->Nb->VerifyLinkIsCoherent (0, CurrentLink, State->Nb)) {
+ State->Nb->StopLink (0, CurrentLink, State, State->Nb);
+ }
+ }
+
+ for (NodeToKill = 0; NodeToKill < MAX_NODES; NodeToKill++) {
+ State->Nb->WriteFullRoutingTable (0, NodeToKill, ROUTE_TO_SELF, ROUTE_TO_SELF, 0, State->Nb);
+ }
+
+ State->HtInterface->CleanMapsAfterError (State);
+
+ // End Coherent Discovery
+ Result = FALSE;
+ }
+ return Result;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Check the system MP capability with a new node and handle any failure.
+ *
+ * Invoke the northbridge MP capability check. If it fails, notify the event and force
+ * 1P. Should not need to stop links on the BSP.
+ *
+ * @param[in] CurrentNode The node we are exploring from
+ * @param[in] CurrentLink The Link on that node to explore.
+ * @param[in] State Access to Northbridge interface.
+ *
+ * @retval TRUE Check is Ok
+ * @retval FALSE Check Failed and is handled
+ */
+BOOLEAN
+STATIC
+CheckCapable (
+ IN UINT8 CurrentNode,
+ IN UINT8 CurrentLink,
+ IN STATE_DATA *State
+ )
+{
+ UINT8 NodeToKill;
+ BOOLEAN Result;
+
+ Result = TRUE;
+
+ // Check the capability of northbridges against the currently known configuration
+ if (State->Nb->IsExceededCapable ((CurrentNode + 1), State, State->Nb)) {
+ IDS_ERROR_TRAP;
+ // Notify BIOS of event
+ NotifyFatalCohMpCapMismatch (
+ CurrentNode,
+ CurrentLink,
+ State->SysMpCap,
+ State->NodesDiscovered,
+ State
+ );
+
+ State->NodesDiscovered = 0;
+ State->TotalLinks = 0;
+
+ for (NodeToKill = 0; NodeToKill < MAX_NODES; NodeToKill++) {
+ State->Nb->WriteFullRoutingTable (0, NodeToKill, ROUTE_TO_SELF, ROUTE_TO_SELF, 0, State->Nb);
+ }
+
+ State->HtInterface->CleanMapsAfterError (State);
+
+ // End Coherent Discovery
+ Result = FALSE;
+ }
+ return Result;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Make all the tests needed to determine if a link should be added to the system data structure.
+ *
+ * The link should be added to the system data structure if it is:
+ * - not being Ignored on this boot
+ * - not having a hard failure
+ * - coherent and connected
+ * - not already in the system data structure
+ * - not subject to some special handling case.
+ * .
+ *
+ * @param[in] CurrentNode The node we are exploring from
+ * @param[in] CurrentLink The Link on that node to explore.
+ * @param[in] State Access to Northbridge interface.
+ *
+ * @retval FALSE This link should not be added.
+ * @retval TRUE This link should explored and added to the system.
+ */
+BOOLEAN
+STATIC
+IsLinkToAdd (
+ IN UINT8 CurrentNode,
+ IN UINT8 CurrentLink,
+ IN STATE_DATA *State
+ )
+{
+ BOOLEAN Linkfound;
+ UINTN Port;
+ FINAL_LINK_STATE FinalLinkState;
+ BOOLEAN Result;
+
+ Result = FALSE;
+
+ FinalLinkState = State->HtInterface->GetIgnoreLink (CurrentNode, CurrentLink, State->Nb->DefaultIgnoreLinkList, State);
+ if ((FinalLinkState != MATCHED) && (FinalLinkState != POWERED_OFF)) {
+ if (!State->Nb->ReadTrueLinkFailStatus (CurrentNode, CurrentLink, State, State->Nb)) {
+ // Make sure that the Link is connected, coherent, and ready
+ if (State->Nb->VerifyLinkIsCoherent (CurrentNode, CurrentLink, State->Nb)) {
+ // Test to see if the CurrentLink has already been explored
+ Linkfound = FALSE;
+ for (Port = 0; Port < State->TotalLinks; Port++) {
+ if ((((*State->PortList)[ (Port * 2 + 1)].NodeID == CurrentNode) &&
+ ((*State->PortList)[ (Port * 2 + 1)].Link == CurrentLink)) ||
+ (((*State->PortList)[ (Port * 2)].NodeID == CurrentNode) &&
+ ((*State->PortList)[ (Port * 2)].Link == CurrentLink))) {
+ Linkfound = TRUE;
+ break;
+ }
+ }
+ if (!Linkfound) {
+ if (!State->Nb->HandleSpecialLinkCase (CurrentNode, CurrentLink, State, State->Nb)) {
+ Result = TRUE;
+ }
+ }
+ }
+ }
+ } else {
+ if (FinalLinkState == POWERED_OFF) {
+ State->Nb->StopLink (CurrentNode, CurrentLink, State, State->Nb);
+ }
+ }
+ return Result;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Explore for a new node over a link, handling whatever is found.
+ *
+ * Open a temporary route over a link on the current node.
+ * Make checks for compatibility and capability in the proper sequence.
+ * If the node found is new, set a token to it, so it will be recognized in the
+ * future, and notify an event for finding a new node.
+ * If the node is already found (token is set), just return status.
+ *
+ * @param[in] CurrentNode The node we are exploring from
+ * @param[in] CurrentLink The Link on that node to explore.
+ * @param[in] LogicalProcessor The processor to update in the maps.
+ * @param[in,out] NewNodeSavedInfo The saved info for nodes in that processor.
+ * @param[in] State Access to Northbridge interface.
+ *
+ * @retval ExploreNodeStatusNew A new node was found
+ * @retval ExploreNodeStatusGood This is a good link to an already known node
+ * @retval ExploreNodeStatusStop Stop Coherent Discovery
+ */
+EXPLORE_NODE_STATUS
+STATIC
+ExploreNode (
+ IN UINT8 CurrentNode,
+ IN UINT8 CurrentLink,
+ IN UINT8 LogicalProcessor,
+ IN OUT NEW_NODE_SAVED_INFO_LIST NewNodeSavedInfo,
+ IN STATE_DATA *State
+ )
+{
+ UINT8 Token;
+ EXPLORE_NODE_STATUS Status;
+
+ // Modify CurrentNode's routing table to use CurrentLink to send
+ // traffic to CurrentNode + 1
+ //
+ State->Nb->WriteRoutingTable (CurrentNode, (CurrentNode + 1), CurrentLink, State->Nb);
+ if (!State->Nb->HandleSpecialNodeCase ((CurrentNode + 1), CurrentLink, State, State->Nb)) {
+ if (CheckCompatible (CurrentNode, CurrentLink, State)) {
+ // Read Token from Current + 1
+ Token = State->Nb->ReadToken ((CurrentNode + 1), State->Nb);
+ ASSERT (Token <= State->NodesDiscovered);
+ if (Token == 0) {
+ State->NodesDiscovered++;
+ ASSERT (State->NodesDiscovered < MAX_NODES);
+ if (CheckCapable (CurrentNode, CurrentLink, State)) {
+ Token = State->NodesDiscovered;
+ State->Nb->WriteToken ((CurrentNode + 1), Token, State->Nb);
+ // Fill in Saved New Node info for the discovered node.
+ // We do this so we don't have to keep a temporary route open to it.
+ // So we save everything that might be needed to set the socket and node
+ // maps for either the software or hardware method.
+ //
+ (*NewNodeSavedInfo)[Token].LogicalProcessor = LogicalProcessor;
+ (*NewNodeSavedInfo)[Token].CurrentNode = CurrentNode;
+ (*NewNodeSavedInfo)[Token].CurrentLink = CurrentLink;
+ (*NewNodeSavedInfo)[Token].PackageLink = State->Nb->GetPackageLink (CurrentNode, CurrentLink, State->Nb);
+ (*NewNodeSavedInfo)[Token].HardwareSocket = State->Nb->GetSocket (Token, (CurrentNode + 1), State->Nb);
+ State->Nb->GetModuleInfo (
+ CurrentNode,
+ &((*NewNodeSavedInfo)[Token].CurrentModuleType),
+ &((*NewNodeSavedInfo)[Token].CurrentModule),
+ State->Nb
+ );
+ State->Nb->GetModuleInfo (
+ (CurrentNode + 1),
+ &((*NewNodeSavedInfo)[Token].NewModuleType),
+ &((*NewNodeSavedInfo)[Token].NewModule),
+ State->Nb
+ );
+
+ // Notify BIOS with info
+ NotifyInfoCohNodeDiscovered (
+ CurrentNode,
+ CurrentLink,
+ Token,
+ (CurrentNode + 1),
+ State
+ );
+ Status = ExploreNodeStatusNew;
+ } else {
+ // Failed Capable
+ Status = ExploreNodeStatusStop;
+ }
+ } else {
+ // Not a new node, token already set
+ Status = ExploreNodeStatusGood;
+ }
+ } else {
+ // Failed Compatible
+ Status = ExploreNodeStatusStop;
+ }
+ } else {
+ // Ignore this node
+ Status = ExploreNodeStatusIgnore;
+ }
+
+ return Status;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Process all the saved new node info for the current processor.
+ *
+ * When all nodes in the processor have been discovered, we can process all the saved
+ * info about the nodes. We add each node to the socket and node maps.
+ *
+ * @param[in] LogicalProcessor The processor to update in the maps.
+ * @param[in] NewNodeSavedInfo The saved info for nodes in that processor.
+ * @param[in] State Our system representation.
+ */
+VOID
+STATIC
+ProcessSavedNodeInfo (
+ IN UINT8 LogicalProcessor,
+ IN NEW_NODE_SAVED_INFO_LIST NewNodeSavedInfo,
+ IN STATE_DATA *State
+ )
+{
+ UINT8 NewNode;
+ UINT8 HardwareSocket;
+
+ // Can't have more processors than nodes, just more (or equal) nodes than processors.
+ ASSERT (LogicalProcessor <= (State->NodesDiscovered));
+ HardwareSocket = 0xFF;
+ // Find the Hardware Socket value to use (if we are using the hardware socket naming method).
+ // The new nodes are the ones in this processor, so find the one that is module 0.
+ for (NewNode = 0; NewNode < (State->NodesDiscovered + 1); NewNode++) {
+ if (((*NewNodeSavedInfo)[NewNode].LogicalProcessor == LogicalProcessor) &&
+ ((*NewNodeSavedInfo)[NewNode].NewModule == 0)) {
+ HardwareSocket = (*NewNodeSavedInfo)[NewNode].HardwareSocket;
+ break;
+ }
+ }
+ // We must have found a result, however, the hardware socket value doesn't have to be correct
+ // unless we are using the hardware socket naming method. Northbridge code should return the
+ // node number for the hardware socket if hardware socket strapping is not supported (i.e. no sbi).
+ ASSERT (HardwareSocket != 0xFF);
+
+ // Set the node to socket maps for this processor. Node zero is always handled specially,
+ // so skip it in this loop.
+ for (NewNode = 1; NewNode < (State->NodesDiscovered + 1); NewNode++) {
+ if ((*NewNodeSavedInfo)[NewNode].LogicalProcessor == LogicalProcessor) {
+ // For the currently discovered logical processor, update node to socket
+ // map for all the processor's nodes.
+ State->HtInterface->SetNodeToSocketMap (
+ (*NewNodeSavedInfo)[NewNode].CurrentNode,
+ (*NewNodeSavedInfo)[NewNode].CurrentModule,
+ (*NewNodeSavedInfo)[NewNode].PackageLink,
+ NewNode,
+ HardwareSocket,
+ (*NewNodeSavedInfo)[NewNode].NewModule,
+ State);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Create and add a new link to the system data structure.
+ *
+ * Add the two port list data structures, source first, initializing
+ * the two node ids and the link values. The node id of the remote
+ * node is its token value. Also, update the adjacency matrix and
+ * node degree table.
+ *
+ * @param[in] CurrentNode The node we are exploring from
+ * @param[in] CurrentLink The Link on that node to explore.
+ * @param[in] TempRoute The temporary node route that goes over that link.
+ * @param[in] State Access to Northbridge interface.
+ *
+ */
+VOID
+STATIC
+AddLinkToSystem (
+ IN UINT8 CurrentNode,
+ IN UINT8 CurrentLink,
+ IN UINT8 TempRoute,
+ IN STATE_DATA *State
+ )
+{
+ UINT8 Token;
+
+ ASSERT (State->TotalLinks < MAX_PLATFORM_LINKS);
+
+ Token = State->Nb->ReadToken (TempRoute, State->Nb);
+
+ (*State->PortList)[State->TotalLinks * 2].Type = PORTLIST_TYPE_CPU;
+ (*State->PortList)[State->TotalLinks * 2].Link = CurrentLink;
+ (*State->PortList)[State->TotalLinks * 2].NodeID = CurrentNode;
+
+ (*State->PortList)[State->TotalLinks * 2 + 1].Type = PORTLIST_TYPE_CPU;
+ (*State->PortList)[State->TotalLinks * 2 + 1].Link = State->Nb->ReadDefaultLink (TempRoute, State->Nb);
+ (*State->PortList)[State->TotalLinks * 2 + 1].NodeID = Token;
+
+ State->TotalLinks++;
+
+ if ( !State->Fabric->SysMatrix[CurrentNode][Token] ) {
+ State->Fabric->SysDegree[CurrentNode]++;
+ State->Fabric->SysDegree[Token]++;
+ State->Fabric->SysMatrix[CurrentNode][Token] = TRUE;
+ State->Fabric->SysMatrix[Token][CurrentNode] = TRUE;
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Start discovery from a new node.
+ *
+ * If the node is not the BSP, establish a route between the node and the
+ * BSP for request/response.
+ * Set the node id, and enable routing on this node. This gives us control
+ * on that node to isolate links, by specifying each link in turn as the route
+ * to a possible new node.
+ *
+ * @param[in] CurrentNode The node we are exploring from
+ * @param[in] State Access to Northbridge interface.
+ *
+ */
+VOID
+STATIC
+StartFromANewNode (
+ IN UINT8 CurrentNode,
+ IN STATE_DATA *State
+ )
+{
+ if (CurrentNode != 0) {
+ // Set path from BSP to CurrentNode
+ routeFromBSP (CurrentNode, CurrentNode, State);
+
+ // Set path from BSP to CurrentNode for CurrentNode + 1 if
+ // CurrentNode + 1 != MAX_NODES
+ //
+ if ((CurrentNode + 1) != MAX_NODES) {
+ routeFromBSP (CurrentNode, (CurrentNode + 1), State);
+ }
+
+ // Configure CurrentNode to route traffic to the BSP through its
+ // default Link
+ //
+ State->Nb->WriteRoutingTable (CurrentNode, 0, State->Nb->ReadDefaultLink (CurrentNode, State->Nb), State->Nb);
+ }
+
+ // Set CurrentNode's NodeID field to CurrentNode
+ State->Nb->WriteNodeID (CurrentNode, CurrentNode, State->Nb);
+
+ // Enable routing tables on CurrentNode
+ State->Nb->EnableRoutingTables (CurrentNode, State->Nb);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Back up from exploring a one-deep internal node.
+ *
+ * When a newly discovered node has internal package links to another
+ * node in the same processor, discovery moves to that node to do the
+ * internal links. Afterwards, this routine provides recovery from that.
+ * The node needs to respond again using deflnk rather than routing, so
+ * that connections from other nodes to that one can be identified.
+ *
+ * @param[in] CurrentNode The node we are exploring from
+ * @param[in] State Access to Northbridge interface.
+ *
+ */
+VOID
+STATIC
+BackUpFromANode (
+ IN UINT8 CurrentNode,
+ IN STATE_DATA *State
+ )
+{
+ if (CurrentNode != 0) {
+ // Disable routing tables on CurrentNode
+ State->Nb->DisableRoutingTables (CurrentNode, State->Nb);
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Dynamically Discover all coherent devices in the system.
+ *
+ * @HtFeatMethod{::F_COHERENT_DISCOVERY}
+ *
+ * Initialize some basics like Node IDs and total Nodes found in the
+ * process. As we go we also build a representation of the discovered
+ * system which we will use later to program the routing tables.
+ * During this step, the routing is via default Link back to BSP and
+ * to each new Node on the Link it was discovered on (no coherency is
+ * active yet).
+ *
+ * In the case of multiple nodes per processor, do a one deep exploration of internal links
+ * to ensure those node pairs are always numbered n, n + 1.
+ *
+ * @param[in,out] State our global state
+ *
+ */
+VOID
+CoherentDiscovery (
+ IN OUT STATE_DATA *State
+ )
+{
+ UINT8 CurrentNode;
+ UINT8 OneDeepNode;
+ UINT8 OneDeepLink;
+ UINT8 CurrentLink;
+ UINT8 LogicalProcessor;
+ EXPLORE_NODE_STATUS ExplorationStatus;
+ LINK_ITERATOR_STATUS LinkIteratorStatus;
+ NEW_NODE_SAVED_INFO_ITEM NewNodeSavedInfoItems [MAX_NODES];
+ NEW_NODE_SAVED_INFO_LIST NewNodeSavedInfo;
+
+ // Initially no info exists for any node, but the BSP is part of logical processor zero.
+ for (CurrentNode = 0; CurrentNode < MAX_NODES; CurrentNode++) {
+ NewNodeSavedInfoItems [CurrentNode] = NoInfoSavedYet;
+ }
+ NewNodeSavedInfoItems[0].LogicalProcessor = 0;
+ NewNodeSavedInfoItems[0].HardwareSocket = State->Nb->GetSocket (0, 0, State->Nb);
+ State->Nb->GetModuleInfo (0, &NewNodeSavedInfoItems[0].NewModuleType, &NewNodeSavedInfoItems[0].NewModule, State->Nb);
+ NewNodeSavedInfo = (NEW_NODE_SAVED_INFO_LIST) NewNodeSavedInfoItems;
+
+ CurrentNode = 0;
+ CurrentLink = LINK_ITERATOR_BEGIN;
+ LogicalProcessor = 0;
+ // An initial status, for node zero if you will.
+ ExplorationStatus = ExploreNodeStatusGood;
+
+ //
+ // Entries are always added in pairs, the even indices are the 'source'
+ // side closest to the BSP, the odd indices are the 'destination' side
+ //
+
+ while ((CurrentNode <= State->NodesDiscovered) && (ExplorationStatus != ExploreNodeStatusStop)) {
+ StartFromANewNode (CurrentNode, State);
+
+ //
+ // Explore all internal links
+ //
+ LinkIteratorStatus = State->Nb->GetNextLink (CurrentNode, &CurrentLink, State->Nb);
+
+ while ((LinkIteratorStatus == LinkIteratorInternal) &&
+ (ExplorationStatus != ExploreNodeStatusStop)) {
+ if (IsLinkToAdd (CurrentNode, CurrentLink, State)) {
+ ExplorationStatus = ExploreNode (CurrentNode, CurrentLink, LogicalProcessor, NewNodeSavedInfo, State);
+ if ((ExplorationStatus == ExploreNodeStatusGood) ||
+ (ExplorationStatus == ExploreNodeStatusNew)) {
+ AddLinkToSystem (CurrentNode, CurrentLink, (CurrentNode + 1), State);
+ }
+ }
+ LinkIteratorStatus = State->Nb->GetNextLink (CurrentNode, &CurrentLink, State->Nb);
+ }
+ if (CurrentNode == 0) {
+ // The BSP processor is completely discovered now.
+ ProcessSavedNodeInfo (LogicalProcessor, NewNodeSavedInfo, State);
+ LogicalProcessor++;
+ }
+
+ //
+ // Explore all the external links from this node.
+ //
+
+ // Starting this iteration using the link that we last got in the iteration above.
+ while ((LinkIteratorStatus == LinkIteratorExternal) &&
+ (ExplorationStatus != ExploreNodeStatusStop)) {
+ if (IsLinkToAdd (CurrentNode, CurrentLink, State)) {
+ ExplorationStatus = ExploreNode (CurrentNode, CurrentLink, LogicalProcessor, NewNodeSavedInfo, State);
+ if (ExplorationStatus == ExploreNodeStatusNew) {
+ AddLinkToSystem (CurrentNode, CurrentLink, (CurrentNode + 1), State);
+ // If this is a new node, we need to explore to its internal mate, if any.
+ // This allows us to keep internal node pairs as ids n, n+1
+ // We use special link and node variables so we can keep our context.
+ OneDeepLink = 0xFF;
+ OneDeepNode = State->Nb->ReadToken ((CurrentNode + 1), State->Nb);
+ StartFromANewNode (OneDeepNode, State);
+ LinkIteratorStatus = State->Nb->GetNextLink (OneDeepNode, &OneDeepLink, State->Nb);
+ while ((LinkIteratorStatus == LinkIteratorInternal) &&
+ (ExplorationStatus != ExploreNodeStatusStop)) {
+ if (IsLinkToAdd (OneDeepNode, OneDeepLink, State)) {
+ ExplorationStatus = ExploreNode (OneDeepNode, OneDeepLink, LogicalProcessor, NewNodeSavedInfo, State);
+ if ((ExplorationStatus == ExploreNodeStatusGood) ||
+ (ExplorationStatus == ExploreNodeStatusNew)) {
+ AddLinkToSystem (OneDeepNode, OneDeepLink, (OneDeepNode + 1), State);
+ }
+ }
+ LinkIteratorStatus = State->Nb->GetNextLink (OneDeepNode, &OneDeepLink, State->Nb);
+ }
+ // Since we completed all the node's internal links, we found all the nodes in that processor.
+ ProcessSavedNodeInfo (LogicalProcessor, NewNodeSavedInfo, State);
+ LogicalProcessor++;
+ // Restore node to discoverable state. Otherwise you can't tell what links it is connected on.
+ BackUpFromANode (OneDeepNode, State);
+ } else {
+ if (ExplorationStatus == ExploreNodeStatusGood) {
+ AddLinkToSystem (CurrentNode, CurrentLink, (CurrentNode + 1), State);
+ }
+ }
+ }
+ LinkIteratorStatus = State->Nb->GetNextLink (CurrentNode, &CurrentLink, State->Nb);
+ }
+ CurrentNode++;
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatDynamicDiscovery.h b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatDynamicDiscovery.h
new file mode 100644
index 0000000000..3c88143ca2
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatDynamicDiscovery.h
@@ -0,0 +1,80 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Coherent Discovery Interface.
+ *
+ * Contains interface to the coherent discovery feature.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 34897 $ @e \$Date: 2010-07-14 10:07:10 +0800 (Wed, 14 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.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _HT_FEAT_DYNAMIC_DISCOVERY_H_
+#define _HT_FEAT_DYNAMIC_DISCOVERY_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/**
+ * Dynamically Discover all coherent devices in the system.
+ *
+ */
+VOID
+CoherentDiscovery (
+ IN OUT STATE_DATA *State
+ );
+
+#endif /* _HT_FEAT_DYNAMIC_DISCOVERY_H_ */
+
+
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]
+ }
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.h b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.h
new file mode 100644
index 0000000000..a9a85b8fbe
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatGanging.h
@@ -0,0 +1,80 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Link Reganging Interface.
+ *
+ * Contains interface to the Reganging feature.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 34897 $ @e \$Date: 2010-07-14 10:07:10 +0800 (Wed, 14 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.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _HT_FEAT_GANGING_H_
+#define _HT_FEAT_GANGING_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/**
+ * Test the subLinks of a Link to see if they qualify to be reganged.
+ *
+ */
+VOID
+RegangLinks (
+ IN OUT STATE_DATA *State
+ );
+
+#endif /* _HT_FEAT_GANGING_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatNoncoherent.c b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatNoncoherent.c
new file mode 100644
index 0000000000..dbef5b888e
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatNoncoherent.c
@@ -0,0 +1,375 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Non-Coherent Discovery Routines.
+ *
+ * Contains routines for enumerating and initializing non-coherent devices.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 35740 $ @e \$Date: 2010-07-30 00:04:17 +0800 (Fri, 30 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 "htNotify.h"
+#include "htNb.h"
+#include "htFeatNoncoherent.h"
+#include "htFeatOptimization.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_HT_FEATURES_HTFEATNONCOHERENT_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define NO_DEVICE 0xFFFFFFFFull
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/***************************************************************************
+ *** Non-coherent init code ***
+ *** Algorithms ***
+ ***************************************************************************/
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Process a non-coherent Link.
+ *
+ * @HtFeatMethod{::F_PROCESS_LINK}
+ *
+ * Enable a range of bus numbers, and set the device ID for all devices found. Add
+ * non-coherent devices, links to the system data structure.
+ *
+ * @param[in] Node Node on which to process nc init
+ * @param[in] Link The non-coherent Link on that Node
+ * @param[in] IsCompatChain Is this the chain with the southbridge? TRUE if yes.
+ * @param[in,out] State our global state
+ */
+VOID
+ProcessLink (
+ IN UINT8 Node,
+ IN UINT8 Link,
+ IN BOOLEAN IsCompatChain,
+ IN OUT STATE_DATA *State
+ )
+{
+ UINT8 SecBus;
+ UINT8 SubBus;
+ UINT32 CurrentBuid;
+ UINT32 Temp;
+ UINT32 UnitIdCount;
+ PCI_ADDR CurrentPtr;
+ PCI_ADDR Link1ControlRegister;
+ UINT8 Depth;
+ BUID_SWAP_LIST *SwapPtr;
+ UINT8 LastLink;
+ BOOLEAN IsCaveDevice;
+
+ ASSERT ((Node < MAX_NODES) && (Link < State->Nb->MaxLinks));
+
+ if (!State->HtInterface->GetOverrideBusNumbers (Node, Link, &SecBus, &SubBus, State)) {
+ // Assign Bus numbers
+ if (State->AutoBusCurrent >= State->HtBlock->AutoBusMax) {
+ // If we run out of Bus Numbers, notify and skip this chain
+ //
+ IDS_ERROR_TRAP;
+ NotifyErrorNcohBusMaxExceed (Node, Link, State->AutoBusCurrent, State);
+ return;
+ }
+
+ if (State->UsedCfgMapEntries >= 4) {
+ // If we have used all the PCI Config maps we can't add another chain.
+ // Notify and if call back is unimplemented or returns, skip this chain.
+ //
+ IDS_ERROR_TRAP;
+ NotifyErrorNcohCfgMapExceed (Node, Link, State);
+ return;
+ }
+
+ SecBus = State->AutoBusCurrent;
+ SubBus = SecBus + State->HtBlock->AutoBusIncrement - 1;
+ State->AutoBusCurrent = State->AutoBusCurrent + State->HtBlock->AutoBusIncrement;
+ }
+
+ State->Nb->SetConfigAddrMap (State->UsedCfgMapEntries, SecBus, SubBus, Node, Link, State, State->Nb);
+ State->UsedCfgMapEntries++;
+
+ if (State->HtInterface->GetManualBuidSwapList (Node, Link, &SwapPtr, State)) {
+ // Manual non-coherent BUID assignment
+ AGESA_TESTPOINT (TpProcHtManualNc, State->ConfigHandle);
+
+
+ if (!IsCompatChain || !State->IsUsingRecoveryHt) {
+ // If this is the not southbridge chain or Recovery HT was not used
+ // then we need to assign BUIDs here.
+ //
+ Depth = 0;
+ // Assign BUID's per manual override
+ while (SwapPtr->Swaps[Depth].FromId != 0xFF) {
+ CurrentPtr.AddressValue = MAKE_SBDFO (0, SecBus, SwapPtr->Swaps[Depth].FromId, 0, 0);
+ if (DoesDeviceHaveHtSubtypeCap (CurrentPtr, HT_SLAVE_CAPABILITY, &CurrentPtr, State)) {
+ // Set the device's BUID field [20:16] to the current buid
+ CurrentBuid = SwapPtr->Swaps[Depth].ToId;
+ LibAmdPciWriteBits (CurrentPtr, 20, 16, &CurrentBuid, State->ConfigHandle);
+ Depth++;
+ } else {
+ // All non-coherent devices must have a slave interface capability.
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ }
+
+ // Build chain of devices. Do this even if Recovery HT assign BUIDs for this chain.
+ Depth = 0;
+ while (SwapPtr->FinalIds[Depth] != 0xFF) {
+ ASSERT (State->TotalLinks < MAX_PLATFORM_LINKS);
+ (*State->PortList)[(State->TotalLinks * 2)].NodeID = Node;
+ // Note: depth == 0 is true before depth > 0. This makes LastLink variable work.
+ if (Depth == 0) {
+ (*State->PortList)[(State->TotalLinks * 2)].Type = PORTLIST_TYPE_CPU;
+ (*State->PortList)[(State->TotalLinks * 2)].Link = Link;
+ } else {
+ // Fill in the host side port. Link and base pointer can be deduced from the upstream link's
+ // downstream port.
+ (*State->PortList)[(State->TotalLinks * 2)].Type = PORTLIST_TYPE_IO;
+ (*State->PortList)[(State->TotalLinks * 2)].Link = 1 - (*State->PortList)[(((State->TotalLinks - 1) * 2) + 1)].Link;
+ (*State->PortList)[(State->TotalLinks * 2)].HostLink = Link;
+ (*State->PortList)[(State->TotalLinks * 2)].HostDepth = Depth - 1;
+ (*State->PortList)[(State->TotalLinks * 2)].Pointer = (*State->PortList)[(((State->TotalLinks - 1) * 2) + 1)].Pointer;
+ }
+
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Type = PORTLIST_TYPE_IO;
+ (*State->PortList)[(State->TotalLinks * 2) + 1].NodeID = Node;
+ (*State->PortList)[(State->TotalLinks * 2) + 1].HostLink = Link;
+ (*State->PortList)[(State->TotalLinks * 2) + 1].HostDepth = Depth;
+
+ CurrentPtr.AddressValue = MAKE_SBDFO (0, SecBus, (SwapPtr->FinalIds[Depth] & 0x3F), 0, 0);
+ if (DoesDeviceHaveHtSubtypeCap (CurrentPtr, HT_SLAVE_CAPABILITY, &CurrentPtr, State)) {
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Pointer = CurrentPtr;
+ } else {
+ // All non-coherent devices must have a slave interface capability.
+ ASSERT (FALSE);
+ break;
+ }
+
+ // Bit 6 indicates whether orientation override is desired.
+ // Bit 7 indicates the upstream Link if overriding.
+ //
+ // assert catches at least the one known incorrect setting, that a non-zero link
+ // is specified, but override desired is not set.
+ ASSERT (((SwapPtr->FinalIds[Depth] & 0x40) != 0) || ((SwapPtr->FinalIds[Depth] & 0x80) == 0));
+ if ((SwapPtr->FinalIds[Depth] & 0x40) != 0) {
+ // Override the device's orientation
+ LastLink = SwapPtr->FinalIds[Depth] >> 7;
+ } else {
+ // Detect the device's orientation, by reading the Master Host bit [26]
+ LibAmdPciReadBits (CurrentPtr, 26, 26, &Temp, State->ConfigHandle);
+ LastLink = (UINT8)Temp;
+ }
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Link = LastLink;
+
+ Depth++;
+ State->TotalLinks++;
+ }
+ } else {
+ // Automatic non-coherent device detection
+ AGESA_TESTPOINT (TpProcHtAutoNc, State->ConfigHandle);
+ IDS_HDT_CONSOLE (HT_TRACE, "Auto IO chain init on node=%d, link=%d, secbus=%d, subbus=%d%s.\n",
+ Node, Link, SecBus, SubBus, (IsCompatChain ? ", Compat" : ""));
+ Depth = 0;
+ CurrentBuid = 1;
+ for (; ; ) {
+ CurrentPtr.AddressValue = MAKE_SBDFO (0, SecBus, 0, 0, 0);
+
+ LibAmdPciRead (AccessWidth32, CurrentPtr, &Temp, State->ConfigHandle);
+ if (Temp == NO_DEVICE) {
+ if (IsCompatChain && State->IsUsingRecoveryHt) {
+ // See if the device is aleady at a non-zero BUID because HT Init Reset aleady assigned it.
+ CurrentPtr.Address.Device = CurrentBuid;
+ LibAmdPciRead (AccessWidth32, CurrentPtr, &Temp, State->ConfigHandle);
+ if (Temp == NO_DEVICE) {
+ // No more devices already assigned.
+ break;
+ }
+ } else {
+ // No more devices found.
+ break;
+ }
+ }
+
+ ASSERT (State->TotalLinks < MAX_PLATFORM_LINKS);
+
+ (*State->PortList)[(State->TotalLinks * 2)].NodeID = Node;
+ if (Depth == 0) {
+ (*State->PortList)[(State->TotalLinks * 2)].Type = PORTLIST_TYPE_CPU;
+ (*State->PortList)[(State->TotalLinks * 2)].Link = Link;
+ } else {
+ // Fill in the host side port. Link and base pointer can be deduced from the upstream link's
+ // downstream port.
+ (*State->PortList)[(State->TotalLinks * 2)].Type = PORTLIST_TYPE_IO;
+ (*State->PortList)[(State->TotalLinks * 2)].Link = 1 - (*State->PortList)[((State->TotalLinks - 1) * 2) + 1].Link;
+ (*State->PortList)[(State->TotalLinks * 2)].HostLink = Link;
+ (*State->PortList)[(State->TotalLinks * 2)].HostDepth = Depth - 1;
+ (*State->PortList)[(State->TotalLinks * 2)].Pointer = (*State->PortList)[((State->TotalLinks - 1) * 2) + 1].Pointer;
+ }
+
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Type = PORTLIST_TYPE_IO;
+ (*State->PortList)[(State->TotalLinks * 2) + 1].NodeID = Node;
+ (*State->PortList)[(State->TotalLinks * 2) + 1].HostLink = Link;
+ (*State->PortList)[(State->TotalLinks * 2) + 1].HostDepth = Depth;
+
+ if (DoesDeviceHaveHtSubtypeCap (CurrentPtr, HT_SLAVE_CAPABILITY, &CurrentPtr, State)) {
+
+ // Get device's unit id count [25:21]
+ LibAmdPciReadBits (CurrentPtr, 25, 21, &UnitIdCount, State->ConfigHandle);
+ if (((UnitIdCount + CurrentBuid) > MAX_BUID) || ((SecBus == 0) && ((UnitIdCount + CurrentBuid) > 24))) {
+ // An error handler for the case where we run out of BUID's on a chain
+ NotifyErrorNcohBuidExceed (Node, Link, Depth, (UINT8)CurrentBuid, (UINT8)UnitIdCount, State);
+ IDS_ERROR_TRAP;
+ break;
+ }
+ // While we are still certain we are accessing this device, remember if it is a cave device.
+ // This is found by reading EOC from the Link 1 Control Register.
+ Link1ControlRegister = CurrentPtr;
+ Link1ControlRegister.Address.Register += (HTSLAVE_LINK01_OFFSET + HTSLAVE_LINK_CONTROL_0_REG);
+ LibAmdPciReadBits (Link1ControlRegister, 6, 6, &Temp, State->ConfigHandle);
+ IsCaveDevice = ((Temp == 0) ? FALSE : TRUE);
+
+ // Attempt to write the new BUID. Unless this chain was aleady assigned BUIDs during Init Reset,
+ // then just re-discover the chain. Note this may be true whether the device was found at
+ // BUID zero or not.
+ IDS_HDT_CONSOLE (HT_TRACE, "Found device at depth=%d, BUID=%d.\n", Depth, CurrentPtr.Address.Device);
+ if (!IsCompatChain || !State->IsUsingRecoveryHt) {
+ IDS_HDT_CONSOLE (HT_TRACE, "Assigning device to BUID=%d.\n", CurrentBuid);
+ LibAmdPciWriteBits (CurrentPtr, 20, 16, &CurrentBuid, State->ConfigHandle);
+ }
+
+ CurrentPtr.Address.Device = CurrentBuid;
+ LibAmdPciReadBits (CurrentPtr, 20, 16, &Temp, State->ConfigHandle);
+ if (Temp != CurrentBuid) {
+ if ((Depth == 0) && IsCaveDevice) {
+ // If the chain only consists of a single cave device, that device may have retained zero
+ // for it's BUID.
+ CurrentPtr.Address.Device = 0;
+ LibAmdPciReadBits (CurrentPtr, 20, 16, &Temp, State->ConfigHandle);
+ if (Temp == 0) {
+ // Per HyperTransport specification, devices not accepting BUID reassignment hardwire BUID to zero.
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Link = 0;
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Pointer = CurrentPtr;
+ State->TotalLinks++;
+ Depth++;
+ // Success!
+ IDS_HDT_CONSOLE (HT_TRACE, "%s Cave left at BUID=0.\n", ((!IsCompatChain || !State->IsUsingRecoveryHt) ? "Compatible" : "Already Assigned"));
+ break;
+ } else if (Temp == CurrentBuid) {
+ // and then, there are the other kind of devices ....
+ // Restore the writable BUID field (which contains the value we just wrote) to zero.
+ Temp = 0;
+ LibAmdPciWriteBits (CurrentPtr, 20, 16, &Temp, State->ConfigHandle);
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Link = 0;
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Pointer = CurrentPtr;
+ State->TotalLinks++;
+ Depth++;
+ // Success!
+ IDS_HDT_CONSOLE (HT_TRACE, "Cave left at BUID=0.\n");
+ break;
+ }
+ }
+ // An error handler for this error,
+ // this often occurs in new BIOS ports and it means you need to use a Manual BUID Swap List.
+ NotifyErrorNcohDeviceFailed (Node, Link, Depth, (UINT8)CurrentBuid, State);
+ IDS_ERROR_TRAP;
+ break;
+ }
+
+ LibAmdPciReadBits (CurrentPtr, 26, 26, &Temp, State->ConfigHandle);
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Link = (UINT8)Temp;
+ (*State->PortList)[(State->TotalLinks * 2) + 1].Pointer = CurrentPtr;
+
+ IDS_HDT_CONSOLE (HT_TRACE, "Device assigned.\n");
+ Depth++;
+ State->TotalLinks++;
+ CurrentBuid += UnitIdCount;
+ } else {
+ // All non-coherent devices must have a slave interface capability.
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ // Provide information on automatic device results
+ NotifyInfoNcohAutoDepth (Node, Link, (Depth - 1), State);
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatNoncoherent.h b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatNoncoherent.h
new file mode 100644
index 0000000000..5f7c8863c8
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatNoncoherent.h
@@ -0,0 +1,81 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Non-Coherent Discovery Interface.
+ *
+ * Contains interface to the Non-Coherent Link processing feature.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 34897 $ @e \$Date: 2010-07-14 10:07:10 +0800 (Wed, 14 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.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _HT_FEAT_NONCOHERENT_H_
+#define _HT_FEAT_NONCOHERENT_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/**
+ * Process a non-coherent Link.
+ *
+ */
+VOID
+ProcessLink (
+ IN UINT8 Node,
+ IN UINT8 Link,
+ IN BOOLEAN IsCompatChain,
+ IN OUT STATE_DATA *State
+ );
+
+#endif /* _HT_FEAT_NONCOHERENT_H_ */
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatOptimization.c b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatOptimization.c
new file mode 100644
index 0000000000..bcd669f799
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatOptimization.c
@@ -0,0 +1,886 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Link Optimization Routines.
+ *
+ * Contains routines for determining width, frequency, and other
+ * Link features
+ *
+ * @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 "IdsHt.h"
+#include "htInterface.h"
+#include "htNb.h"
+#include "htFeatOptimization.h"
+#include "htNotify.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_HT_FEATURES_HTFEATOPTIMIZATION_FILECODE
+
+extern CONST PF_HtIdsGetPortOverride ROMDATA pf_HtIdsGetPortOverride;
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+#define PCI_CONFIG_COMMAND_REG04 4
+#define PCI_CONFIG_REVISION_REG08 8
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/***************************************************************************
+ *** Link Optimization ***
+ ***************************************************************************/
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Given the bits set in the register field, return the width it represents.
+ *
+ * As invalid width values or encodings are rare except during debug, catch those using
+ * ASSERT(). This means theoretically we are returning an incorrect result if that
+ * happens. The default chosen for the result is arbitrarily 8 bits. This is likely
+ * not to be the actual correct width and may cause a crash, hang, or incorrect operation.
+ * Hardware often ignores writes of invalid width encodings.
+ *
+ * @note This routine is used for CPUs as well as IO devices, as all comply to the
+ * "HyperTransport I/O Link Specification ".
+ *
+ * @param[in] Value The bits for the register
+ *
+ * @return The width
+ */
+UINT8
+STATIC
+ConvertBitsToWidth (
+ IN UINT8 Value
+ )
+{
+ UINT8 Result;
+
+ Result = 0;
+
+ switch (Value) {
+
+ case 1:
+ Result = 16;
+ break;
+
+ case 0:
+ Result = 8;
+ break;
+
+ case 3:
+ Result = 32;
+ break;
+
+ case 5:
+ Result = 4;
+ break;
+
+ case 4:
+ Result = 2;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+ return Result;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Translate a desired width setting to the bits to set in the register field.
+ *
+ * As invalid width values or encodings are rare except during debug, catch those using
+ * ASSERT(). This means theoretically we are returning an incorrect result if that
+ * happens. The default chosen for the result is arbitrarily 8 bits. This is likely
+ * not to be the actual correct width and may cause a crash, hang, or incorrect operation.
+ * Hardware often ignores writes of invalid width encodings.
+ *
+ * @note This routine is used for CPUs as well as IO devices, as all comply to the
+ * "HyperTransport I/O Link Specification ".
+ *
+ * @param[in] Value the width Value
+ *
+ * @return The bits for the register
+ */
+UINT8
+ConvertWidthToBits (
+ IN UINT8 Value
+ )
+{
+ UINT8 Result;
+
+ Result = 8;
+
+ switch (Value) {
+
+ case 16:
+ Result = 1;
+ break;
+
+ case 8:
+ Result = 0;
+ break;
+
+ case 32:
+ Result = 3;
+ break;
+
+ case 4:
+ Result = 5;
+ break;
+
+ case 2:
+ Result = 4;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ }
+ return Result;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Access HT Link Control Register.
+ *
+ * @HtFeatMethod{::F_SET_HT_CONTROL_REGISTER_BITS}
+ *
+ * Provide a common routine for accessing the HT Link Control registers (84, a4, c4,
+ * e4), to enforce not clearing the HT CRC error bits. Replaces direct use of
+ * AmdPCIWriteBits().
+ *
+ * @note: This routine is called for CPUs as well as IO Devices! All comply to the
+ * "HyperTransport I/O Link Specification ".
+ *
+ * @param[in] Reg the PCI config address the control register
+ * @param[in] HiBit the high bit number
+ * @param[in] LoBit the low bit number
+ * @param[in] Value the value to write to that bit range. Bit 0 => loBit.
+ * @param[in] State Our state, config handle for lib
+ */
+VOID
+SetHtControlRegisterBits (
+ IN PCI_ADDR Reg,
+ IN UINT8 HiBit,
+ IN UINT8 LoBit,
+ IN UINT32 *Value,
+ IN STATE_DATA *State
+ )
+{
+ UINT32 Temp;
+ UINT32 mask;
+
+ ASSERT ((HiBit < 32) && (LoBit < 32) && (HiBit >= LoBit) && ((Reg.AddressValue & 0x3) == 0));
+ ASSERT ((HiBit < 8) || (LoBit > 9));
+
+ // A 1 << 32 == 1 << 0 due to x86 SHL instruction, so skip if that is the case
+ if ((HiBit - LoBit) != 31) {
+ mask = (((UINT32)1 << (HiBit - LoBit + 1)) - 1);
+ } else {
+ mask = (UINT32)0xFFFFFFFF;
+ }
+
+ LibAmdPciRead (AccessWidth32, Reg, &Temp, State->ConfigHandle);
+ Temp &= ~(mask << LoBit);
+ Temp |= (*Value & mask) << LoBit;
+ Temp &= (UINT32)HT_CONTROL_CLEAR_CRC;
+ LibAmdPciWrite (AccessWidth32, Reg, &Temp, State->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Set HT Frequency register for IO Devices
+ *
+ * Provide a common routine for accessing the HT Link Frequency registers at offset 8
+ * and 0x10, to enforce not clearing the HT Link error bits. Replaces direct use of
+ * AmdPCIWriteBits().
+ *
+ * @note This routine is called for IO Devices only!! All comply to the
+ * "HyperTransport I/O Link Specification ".
+ *
+ * @param[in] Reg the PCI config address the control register
+ * @param[in] Hibit the high bit number
+ * @param[in] Lobit the low bit number
+ * @param[in] Value the value to write to that bit range. Bit 0 => loBit.
+ * @param[in] State Our state, config handle for lib
+ */
+VOID
+STATIC
+SetHtIoFrequencyRegisterBits (
+ IN PCI_ADDR Reg,
+ IN UINT8 Hibit,
+ IN UINT8 Lobit,
+ IN UINT32 *Value,
+ IN STATE_DATA *State
+ )
+{
+ UINT32 Mask;
+ UINT32 Temp;
+
+ ASSERT ((Hibit < 32) && (Lobit < 32) && (Hibit >= Lobit) && ((Reg.AddressValue & 0x3) == 0));
+ ASSERT ((Hibit < 12) || (Lobit > 14));
+
+ // A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case
+ if ((Hibit - Lobit) != 31) {
+ Mask = (((UINT32)1 << ((Hibit - Lobit) + 1)) - 1);
+ } else {
+ Mask = (UINT32)0xFFFFFFFF;
+ }
+
+ LibAmdPciRead (AccessWidth32, Reg, &Temp, State->ConfigHandle);
+ Temp &= ~(Mask << Lobit);
+ Temp |= (*Value & Mask) << Lobit;
+ Temp &= (UINT32)HT_FREQUENCY_CLEAR_LINK_ERRORS;
+ LibAmdPciWrite (AccessWidth32, Reg, &Temp, State->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Get Link features into system data structure.
+ *
+ * @HtFeatMethod{::F_GATHER_LINK_DATA}
+ *
+ * For all discovered Links, populate the port list with the frequency and width
+ * capabilities. Gather support data for:
+ * - Unit ID Clumping
+ *
+ * @param[in] State our global state, port list
+ */
+VOID
+GatherLinkData (
+ IN STATE_DATA *State
+ )
+{
+ UINT8 i;
+ PCI_ADDR LinkBase;
+ PCI_ADDR Reg;
+ UINT32 Bits;
+ UINT8 Revision;
+
+ // Get the capability base for whatever device type the link port is on
+ for (i = 0; i < (State->TotalLinks * 2); i++) {
+ if ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) {
+ LinkBase = State->Nb->MakeLinkBase ((*State->PortList)[i].NodeID, (*State->PortList)[i].Link, State->Nb);
+ (*State->PortList)[i].Pointer = LinkBase;
+ } else {
+ LinkBase = (*State->PortList)[i].Pointer;
+ if ((*State->PortList)[i].Link == 1) {
+ LinkBase.Address.Register += HTSLAVE_LINK01_OFFSET;
+ }
+ }
+
+ // Getting the Width is standard across device types
+ Reg = LinkBase;
+ Reg.Address.Register += HTSLAVE_LINK_CONTROL_0_REG;
+ LibAmdPciReadBits (Reg, 22, 20, &Bits, State->ConfigHandle);
+ (*State->PortList)[i].PrvWidthOutCap = ConvertBitsToWidth ((UINT8)Bits);
+
+ LibAmdPciReadBits (Reg, 18, 16, &Bits, State->ConfigHandle);
+ (*State->PortList)[i].PrvWidthInCap = ConvertBitsToWidth ((UINT8)Bits);
+
+ // Get Frequency and other device type specific features
+ if ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) {
+ State->Nb->GatherLinkFeatures (&(*State->PortList)[i], State->HtInterface, State->PlatformConfiguration, State->Nb);
+ } else {
+ Reg = LinkBase;
+ Reg.Address.Register += HTSLAVE_FREQ_REV_0_REG;
+ LibAmdPciReadBits (Reg, 31, 16, &Bits, State->ConfigHandle);
+ (*State->PortList)[i].PrvFrequencyCap = Bits;
+
+ // Unit ID Clumping Support
+ if (State->IsUsingUnitIdClumping) {
+ if (DoesDeviceHaveHtSubtypeCap (LinkBase, HT_UNITID_CAPABILITY, &Reg, State)) {
+ Reg.Address.Register += HTUNIT_SUPPORT_REG;
+ LibAmdPciReadBits (Reg, 31, 0, &Bits, State->ConfigHandle);
+ } else {
+ // Not there, that's ok, we don't know that it should have one.
+ // Check for Passive support. (Bit 0 won't be set if full support is implemented,
+ // so we can use it to indicate passive support in our portlist struct).
+ Reg = LinkBase;
+ Reg.Address.Register += HTSLAVE_FEATURECAP_REG;
+ Bits = 1;
+ LibAmdPciWriteBits (Reg, 5, 5, &Bits, State->ConfigHandle);
+ LibAmdPciReadBits (Reg, 5, 5, &Bits, State->ConfigHandle);
+ }
+ (*State->PortList)[i].ClumpingSupport = Bits;
+ } else {
+ (*State->PortList)[i].ClumpingSupport = HT_CLUMPING_DISABLE;
+ }
+
+ Reg = LinkBase;
+ Reg.Address.Register = PCI_CONFIG_REVISION_REG08;
+ LibAmdPciReadBits ( LinkBase, 7, 0, &Bits, State->ConfigHandle);
+ Revision = (UINT8) Bits;
+
+ LinkBase.Address.Register = 0;
+ LibAmdPciRead (AccessWidth32, LinkBase, &Bits, State->ConfigHandle);
+
+ State->HtInterface->GetDeviceCapOverride ((*State->PortList)[i].NodeID,
+ (*State->PortList)[i].HostLink,
+ (*State->PortList)[i].HostDepth,
+ (*State->PortList)[i].Pointer,
+ Bits,
+ Revision,
+ (*State->PortList)[i].Link,
+ &((*State->PortList)[i].PrvWidthInCap),
+ &((*State->PortList)[i].PrvWidthOutCap),
+ &((*State->PortList)[i].PrvFrequencyCap),
+ &((*State->PortList)[i].ClumpingSupport),
+ State);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Optimize Links.
+ *
+ * @HtFeatMethod{::F_SELECT_OPTIMAL_WIDTH_AND_FREQUENCY}
+ *
+ * For all Links:
+ * Examine both sides of a Link and determine the optimal frequency and width,
+ * taking into account externally provided limits and enforcing any other limit
+ * or matching rules as applicable except subLink balancing. Update the port
+ * list data with the optimal settings.
+ *
+ * @note no hardware state changes in this routine.
+ *
+ * @param[in,out] State Process and update portlist
+ */
+VOID
+SelectOptimalWidthAndFrequency (
+ IN OUT STATE_DATA *State
+ )
+{
+ UINT8 i;
+ UINT8 j;
+ UINT8 Freq;
+ UINT32 Temp;
+ UINT32 CbPcbFreqLimit;
+ UINT8 CbPcbABDownstreamWidth;
+ UINT8 CbPcbBAUpstreamWidth;
+
+ for (i = 0; i < (State->TotalLinks * 2); i += 2) {
+ CbPcbFreqLimit = HT_FREQUENCY_NO_LIMIT;
+ CbPcbABDownstreamWidth = HT_WIDTH_16_BITS;
+ CbPcbBAUpstreamWidth = HT_WIDTH_16_BITS;
+
+ if (((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) && ((*State->PortList)[i + 1].Type == PORTLIST_TYPE_CPU)) {
+ State->HtInterface->GetCpu2CpuPcbLimits ((*State->PortList)[i].NodeID,
+ (*State->PortList)[i].Link,
+ (*State->PortList)[i + 1].NodeID,
+ (*State->PortList)[i + 1].Link,
+ &CbPcbABDownstreamWidth,
+ &CbPcbBAUpstreamWidth,
+ &CbPcbFreqLimit,
+ State
+ );
+ } else {
+ State->HtInterface->GetIoPcbLimits ((*State->PortList)[i + 1].NodeID,
+ (*State->PortList)[i + 1].HostLink,
+ (*State->PortList)[i + 1].HostDepth,
+ &CbPcbABDownstreamWidth,
+ &CbPcbBAUpstreamWidth,
+ &CbPcbFreqLimit,
+ State
+ );
+ }
+
+ Temp = (*State->PortList)[i].PrvFrequencyCap;
+ Temp &= (*State->PortList)[i + 1].PrvFrequencyCap;
+ Temp &= CbPcbFreqLimit;
+ (*State->PortList)[i].CompositeFrequencyCap = (UINT32)Temp;
+ (*State->PortList)[i + 1].CompositeFrequencyCap = (UINT32)Temp;
+
+ ASSERT (Temp != 0);
+ Freq = LibAmdBitScanReverse (Temp);
+ (*State->PortList)[i].SelFrequency = Freq;
+ (*State->PortList)[i + 1].SelFrequency = Freq;
+
+ Temp = (*State->PortList)[i].PrvWidthOutCap;
+ if ((*State->PortList)[i + 1].PrvWidthInCap < Temp) {
+ Temp = (*State->PortList)[i + 1].PrvWidthInCap;
+ }
+ if (CbPcbABDownstreamWidth < Temp) {
+ Temp = CbPcbABDownstreamWidth;
+ }
+ (*State->PortList)[i].SelWidthOut = (UINT8)Temp;
+ (*State->PortList)[i + 1].SelWidthIn = (UINT8)Temp;
+
+ Temp = (*State->PortList)[i].PrvWidthInCap;
+ if ((*State->PortList)[i + 1].PrvWidthOutCap < Temp) {
+ Temp = (*State->PortList)[i + 1].PrvWidthOutCap;
+ }
+ if (CbPcbBAUpstreamWidth < Temp) {
+ Temp = CbPcbBAUpstreamWidth;
+ }
+ (*State->PortList)[i].SelWidthIn = (UINT8)Temp;
+ (*State->PortList)[i + 1].SelWidthOut = (UINT8)Temp;
+ }
+ // Calculate unit id clumping
+ //
+ // Find the root of each IO Chain, process the chain for clumping support.
+ // The root is always the first link of the chain in the port list.
+ // Clumping is not device link specific, so we can just look at the upstream ports (j+1). Use ASSERTs to sanity
+ // check the downstream ports (j). If any device on the chain does not support clumping, the entire chain will be
+ // disabled for clumping.
+ // After analyzing the clumping support on the chain the CPU's portlist has the enable mask. Update all the
+ // IO Devices on the chain with the enable mask. If any device's only have passive support, that is already enabled.
+ //
+ if (State->IsUsingUnitIdClumping) {
+ for (i = 0; i < (State->TotalLinks * 2); i += 2) {
+ if (((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) && ((*State->PortList)[i + 1].Type == PORTLIST_TYPE_IO)) {
+ (*State->PortList)[i].ClumpingSupport = HT_CLUMPING_DISABLE;
+ if ((*State->PortList)[i + 1].ClumpingSupport != HT_CLUMPING_DISABLE) {
+ (*State->PortList)[i].ClumpingSupport |= (*State->PortList)[i + 1].ClumpingSupport;
+ for (j = i + 2; j < (State->TotalLinks * 2); j += 2) {
+ if (((*State->PortList)[j].Type == PORTLIST_TYPE_IO) && ((*State->PortList)[j + 1].Type == PORTLIST_TYPE_IO)) {
+ if (((*State->PortList)[i].NodeID == (*State->PortList)[j + 1].NodeID) &&
+ ((*State->PortList)[i].Link == (*State->PortList)[j + 1].HostLink)) {
+ ASSERT (((*State->PortList)[i].NodeID == (*State->PortList)[j + 1].NodeID) &&
+ ((*State->PortList)[i].Link == (*State->PortList)[j].HostLink));
+ if ((*State->PortList)[j + 1].ClumpingSupport != HT_CLUMPING_DISABLE) {
+ ASSERT ((((*State->PortList)[j + 1].ClumpingSupport & HT_CLUMPING_PASSIVE) == 0) ||
+ (((*State->PortList)[j + 1].ClumpingSupport & ~(HT_CLUMPING_PASSIVE)) == 0));
+ (*State->PortList)[i].ClumpingSupport |= (*State->PortList)[j + 1].ClumpingSupport;
+ } else {
+ (*State->PortList)[i].ClumpingSupport = HT_CLUMPING_DISABLE;
+ break;
+ }
+ }
+ }
+ }
+ if ((*State->PortList)[i + 1].ClumpingSupport != HT_CLUMPING_PASSIVE) {
+ (*State->PortList)[i + 1].ClumpingSupport = (*State->PortList)[i].ClumpingSupport;
+ }
+ for (j = i + 2; j < (State->TotalLinks * 2); j += 2) {
+ if (((*State->PortList)[j].Type == PORTLIST_TYPE_IO) && ((*State->PortList)[j + 1].Type == PORTLIST_TYPE_IO)) {
+ if (((*State->PortList)[i].NodeID == (*State->PortList)[j + 1].NodeID) &&
+ ((*State->PortList)[i].Link == (*State->PortList)[j + 1].HostLink)) {
+ if ((*State->PortList)[j + 1].ClumpingSupport != HT_CLUMPING_PASSIVE) {
+ (*State->PortList)[j + 1].ClumpingSupport = (*State->PortList)[i].ClumpingSupport;
+ // The downstream isn't really passive, just mark it so in order to write the device only once.
+ (*State->PortList)[j].ClumpingSupport = HT_CLUMPING_PASSIVE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Change the hardware state for all Links according to the now optimized data in the
+ * port list data structure.
+ *
+ * @HtFeatMethod{::F_SET_LINK_DATA}
+ *
+ * @param[in] State our global state, port list
+ */
+VOID
+SetLinkData (
+ IN STATE_DATA *State
+ )
+{
+ UINT8 i;
+ PCI_ADDR LinkBase;
+ PCI_ADDR Reg;
+ UINT32 Temp;
+ UINT32 Widthin;
+ UINT32 Widthout;
+ UINT32 Bits;
+ PCI_ADDR CurrentPtr;
+ HTIDS_PORT_OVERRIDE_LIST PortOverrides;
+
+ PortOverrides = NULL;
+
+ for (i = 0; i < (State->TotalLinks * 2); i++) {
+
+ ASSERT ((*State->PortList)[i & 0xFE].SelWidthOut == (*State->PortList)[ (i & 0xFE) + 1].SelWidthIn);
+ ASSERT ((*State->PortList)[i & 0xFE].SelWidthIn == (*State->PortList)[ (i & 0xFE) + 1].SelWidthOut);
+ ASSERT ((*State->PortList)[i & 0xFE].SelFrequency == (*State->PortList)[ (i & 0xFE) + 1].SelFrequency);
+
+ if ((*State->PortList)[i].SelRegang) {
+ ASSERT ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU);
+ ASSERT ((*State->PortList)[i].Link < 4);
+ State->Nb->SetLinkRegang (
+ (*State->PortList)[i].NodeID,
+ (*State->PortList)[i].Link,
+ State->Nb
+ );
+ }
+
+ //
+ // IDS port override for CPUs and IO Devices
+ //
+ pf_HtIdsGetPortOverride ((BOOLEAN) ((i & 1) == 0), &(*State->PortList)[i], &(*State->PortList)[i + 1], &PortOverrides, State);
+
+ LinkBase = (*State->PortList)[i].Pointer;
+ if (((*State->PortList)[i].Type == PORTLIST_TYPE_IO) && ((*State->PortList)[i].Link == 1)) {
+ LinkBase.Address.Register += HTSLAVE_LINK01_OFFSET;
+ }
+
+ // HT CRC Feature, set if configured. The default is not to set it, because with some chipsets it
+ // will lock up if done here.
+ if (State->IsSetHtCrcFlood) {
+ Temp = 1;
+ Reg = LinkBase;
+ Reg.Address.Register += HTHOST_LINK_CONTROL_REG;
+ State->HtFeatures->SetHtControlRegisterBits (Reg, 1, 1, &Temp, State);
+ if ((*State->PortList)[i].Type == PORTLIST_TYPE_IO) {
+ // IO Devices also need to have SERR enabled.
+ Reg = LinkBase;
+ Reg.Address.Register = PCI_CONFIG_COMMAND_REG04;
+ LibAmdPciWriteBits (Reg, 8, 8, &Temp, State->ConfigHandle);
+ }
+ }
+
+ // Some IO devices don't work properly when setting widths, so write them in a single operation,
+ // rather than individually.
+ //
+ Widthout = ConvertWidthToBits ((*State->PortList)[i].SelWidthOut);
+ ASSERT (Widthout == 1 || Widthout == 0 || Widthout == 5 || Widthout == 4);
+ Widthin = ConvertWidthToBits ((*State->PortList)[i].SelWidthIn);
+ ASSERT (Widthin == 1 || Widthin == 0 || Widthin == 5 || Widthin == 4);
+
+ Temp = (Widthin & 7) | ((Widthout & 7) << 4);
+ Reg = LinkBase;
+ Reg.Address.Register += HTHOST_LINK_CONTROL_REG;
+ State->HtFeatures->SetHtControlRegisterBits (Reg, 31, 24, &Temp, State);
+
+ Temp = (*State->PortList)[i].SelFrequency;
+ if ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) {
+ State->Nb->SetLinkFrequency (
+ (*State->PortList)[i].NodeID,
+ (*State->PortList)[i].Link,
+ (UINT8)Temp,
+ State->Nb
+ );
+ } else {
+ ASSERT (Temp <= HT_FREQUENCY_2600M);
+ // Write the frequency setting
+ Reg = LinkBase;
+ Reg.Address.Register += HTSLAVE_FREQ_REV_0_REG;
+ SetHtIoFrequencyRegisterBits (Reg, 11, 8, &Temp, State);
+
+ // Handle additional HT3 frequency requirements, if needed,
+ // or clear them if switching down to ht1 on a warm reset.
+ // Gen1 = 200Mhz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz
+ //
+ // Even though we assert if debugging, we need to check that the capability was
+ // found always, since this is an unknown hardware device, also we are taking
+ // unqualified frequency from the external interface (could be trying to do ht3
+ // on an ht1 IO device).
+ //
+
+ if (Temp > HT_FREQUENCY_1000M) {
+ // Enabling features if gen 3
+ Bits = 1;
+ } else {
+ // Disabling features if gen 1
+ Bits = 0;
+ }
+
+ // Retry Enable
+ if (DoesDeviceHaveHtSubtypeCap (LinkBase, HT_RETRY_CAPABILITY, &CurrentPtr, State)) {
+ ASSERT ((*State->PortList)[i].Link < 2);
+ CurrentPtr.Address.Register += HTRETRY_CONTROL_REG;
+ LibAmdPciWriteBits (CurrentPtr,
+ ((*State->PortList)[i].Link * 16),
+ ((*State->PortList)[i].Link * 16),
+ &Bits,
+ State->ConfigHandle);
+ } else {
+ // If we are turning it off, that may mean the device was only ht1 capable,
+ // so don't complain that we can't do it.
+ //
+ if (Bits != 0) {
+ NotifyWarningOptRequiredCapRetry ((*State->PortList)[i].NodeID,
+ (*State->PortList)[i].HostLink,
+ (*State->PortList)[i].HostDepth,
+ State);
+ }
+ }
+
+ // Scrambling enable
+ if (DoesDeviceHaveHtSubtypeCap (LinkBase, HT_GEN3_CAPABILITY, &CurrentPtr, State)) {
+ ASSERT ((*State->PortList)[i].Link < 2);
+ CurrentPtr.Address.Register = CurrentPtr.Address.Register +
+ HTGEN3_LINK_TRAINING_0_REG +
+ ((*State->PortList)[i].Link * HTGEN3_LINK01_OFFSET);
+ LibAmdPciWriteBits (CurrentPtr, 3, 3, &Bits, State->ConfigHandle);
+ } else {
+ // If we are turning it off, that may mean the device was only ht1 capable,
+ // so don't complain that we can't do it.
+ //
+ if (Bits != 0) {
+ NotifyWarningOptRequiredCapGen3 ((*State->PortList)[i].NodeID,
+ (*State->PortList)[i].HostLink,
+ (*State->PortList)[i].HostDepth,
+ State);
+ }
+ }
+ }
+ // Enable Unit ID Clumping if supported.
+ if (State->IsUsingUnitIdClumping) {
+ if (((*State->PortList)[i].ClumpingSupport != HT_CLUMPING_PASSIVE) &&
+ ((*State->PortList)[i].ClumpingSupport != HT_CLUMPING_DISABLE)) {
+ Bits = (*State->PortList)[i].ClumpingSupport;
+ if ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) {
+ State->Nb->SetLinkUnitIdClumping (
+ (*State->PortList)[i].NodeID,
+ (*State->PortList)[i].Link,
+ (*State->PortList)[i].ClumpingSupport,
+ State->Nb
+ );
+ } else {
+ if (DoesDeviceHaveHtSubtypeCap (LinkBase, HT_UNITID_CAPABILITY, &Reg, State)) {
+ Reg.Address.Register += HTUNIT_ENABLE_REG;
+ LibAmdPciWriteBits (Reg, 31, 0, &Bits, State->ConfigHandle);
+ } else {
+ // If we found one when gathering support, we have to find one now.
+ ASSERT (FALSE);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------------------*/
+/**
+ * Find a specific HT capability type.
+ *
+ * Search all the PCI Config space capabilities on any type of device for an
+ * HT capability of the specific subtype.
+ *
+ * @param[in] DevicePointer A PCI Config address somewhere in the device config space
+ * @param[in] CapSubType The HT capability subtype to find
+ * @param[out] CapabilityBase The Config space base address of the capability, if found.
+ * @param[in] State Our State
+ *
+ * @retval TRUE the capability was found
+ * @retval FALSE the capability was not found
+ */
+BOOLEAN
+DoesDeviceHaveHtSubtypeCap (
+ IN PCI_ADDR DevicePointer,
+ IN UINT8 CapSubType,
+ OUT PCI_ADDR *CapabilityBase,
+ IN STATE_DATA *State
+ )
+{
+ BOOLEAN IsFound;
+ BOOLEAN IsDone;
+ PCI_ADDR Reg;
+ UINT32 Temp;
+ UINT32 RegSubType;
+ UINT32 RegSubTypeMask;
+
+ // Set the PCI Config Space base and the match value.
+ IsFound = FALSE;
+ IsDone = FALSE;
+ Reg = DevicePointer;
+ Reg.Address.Register = 0;
+ if (CapSubType < (HT_HOST_CAPABILITY + 1)) {
+ // HT Interface sub type
+ RegSubType = ((UINT32) (CapSubType << 29) | (UINT32)8);
+ RegSubTypeMask = HT_INTERFACE_CAP_SUBTYPE_MASK;
+ } else {
+ // Other HT capability subtype
+ RegSubType = ((UINT32) (CapSubType << 27) | (UINT32)8);
+ RegSubTypeMask = HT_CAP_SUBTYPE_MASK;
+ }
+ (*CapabilityBase).AddressValue = (UINT32)ILLEGAL_SBDFO;
+
+ // Find it
+ do {
+ LibAmdPciFindNextCap (&Reg, State->ConfigHandle);
+ if (Reg.AddressValue != (UINT32)ILLEGAL_SBDFO) {
+ LibAmdPciRead (AccessWidth32, Reg, &Temp, State->ConfigHandle);
+ // HyperTransport and subtype capability ?
+ if ((Temp & RegSubTypeMask) == RegSubType) {
+ *CapabilityBase = Reg;
+ IsFound = TRUE;
+ }
+ // Some other capability, keep looking
+ } else {
+ // Not there
+ IsDone = TRUE;
+ }
+ } while (!IsFound && !IsDone);
+
+ return IsFound;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Retry must be enabled on all coherent links if it is enabled on any coherent links.
+ *
+ * @HtFeatMethod{::F_SET_LINK_DATA}
+ *
+ * Effectively, this means HT3 on some links cannot be mixed with HT1 on others.
+ * Scan the CPU to CPU links for this condition and limit those frequencies to HT1
+ * if it is detected.
+ * (Non-coherent links are independent.)
+ *
+ * @param[in,out] State global state, port frequency settings.
+ *
+ * @retval TRUE Fixup occurred, all coherent links HT1
+ * @retval FALSE No changes
+ */
+BOOLEAN
+IsCoherentRetryFixup (
+ IN STATE_DATA *State
+ )
+{
+ UINT8 Freq;
+ UINT8 i;
+ UINT8 DetectedFrequencyState;
+ BOOLEAN IsMixed;
+ UINT32 Temp;
+
+ //
+ // detectedFrequencyState:
+ // 0 - initial state
+ // 1 - HT1 Frequencies detected
+ // 2 - HT3 Frequencies detected
+ //
+ IsMixed = FALSE;
+ DetectedFrequencyState = 0;
+
+ // Scan coherent links for a mix of HT3 / HT1
+ for (i = 0; i < (State->TotalLinks * 2); i += 2) {
+ if (((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) && ((*State->PortList)[i + 1].Type == PORTLIST_TYPE_CPU)) {
+ // At this point, Frequency of port [i+1] must equal [i], so just check one of them.
+ switch (DetectedFrequencyState) {
+ case 0:
+ // Set current state to indicate what link frequency we found first
+ if ((*State->PortList)[i].SelFrequency > HT_FREQUENCY_1000M) {
+ // HT3 frequencies
+ DetectedFrequencyState = 2;
+ } else {
+ // HT1 frequencies
+ DetectedFrequencyState = 1;
+ }
+ break;
+ case 1:
+ // If HT1 frequency detected, fail any HT3 frequency
+ if ((*State->PortList)[i].SelFrequency > HT_FREQUENCY_1000M) {
+ IsMixed = TRUE;
+ }
+ break;
+ case 2:
+ // If HT3 frequency detected, fail any HT1 frequency
+ if ((*State->PortList)[i].SelFrequency <= HT_FREQUENCY_1000M) {
+ IsMixed = TRUE;
+ }
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ if (IsMixed) {
+ // Don't need to keep checking after we find a mix.
+ break;
+ }
+ }
+ }
+
+ if (IsMixed) {
+ for (i = 0; i < (State->TotalLinks * 2); i += 2) {
+ if (((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) && ((*State->PortList)[i + 1].Type == PORTLIST_TYPE_CPU)) {
+ // Limit coherent links to HT 1 frequencies.
+ Temp = (*State->PortList)[i].CompositeFrequencyCap & (*State->PortList)[i + 1].CompositeFrequencyCap;
+ Temp &= HT_FREQUENCY_LIMIT_HT1_ONLY;
+ ASSERT (Temp != 0);
+ (*State->PortList)[i].CompositeFrequencyCap = Temp;
+ (*State->PortList)[i + 1].CompositeFrequencyCap = Temp;
+ Freq = LibAmdBitScanReverse (Temp);
+ (*State->PortList)[i].SelFrequency = Freq;
+ (*State->PortList)[i + 1].SelFrequency = Freq;
+ }
+ }
+ }
+ return (IsMixed);
+}
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatOptimization.h b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatOptimization.h
new file mode 100644
index 0000000000..d6d476418a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatOptimization.h
@@ -0,0 +1,140 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Link Optimization Feature.
+ *
+ * Contains interface for Link Optimization.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 34897 $ @e \$Date: 2010-07-14 10:07:10 +0800 (Wed, 14 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.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _HT_FEAT_OPTIMIZATION_H_
+#define _HT_FEAT_OPTIMIZATION_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/**
+ * Translate a desired width setting to the bits to set in the register field.
+ */
+UINT8
+ConvertWidthToBits (
+ IN UINT8 Value
+ );
+
+/**
+ * Access HT Link Control Register.
+ *
+ */
+VOID
+SetHtControlRegisterBits (
+ IN PCI_ADDR Reg,
+ IN UINT8 HiBit,
+ IN UINT8 LoBit,
+ IN UINT32 *Value,
+ IN STATE_DATA *State
+ );
+
+/**
+ * Get Link features into system data structure.
+ *
+ */
+VOID
+GatherLinkData (
+ IN STATE_DATA *State
+ );
+
+/**
+ * Optimize Links.
+ *
+ */
+VOID
+SelectOptimalWidthAndFrequency (
+ IN OUT STATE_DATA *State
+ );
+
+/**
+ * Change the hardware state for all Links according to the now optimized data in the
+ * port list data structure.
+ *
+ */
+VOID
+SetLinkData (
+ IN STATE_DATA *State
+ );
+
+/**
+ * Retry must be enabled on all coherent links if it is enabled on any coherent links.
+ *
+ */
+BOOLEAN
+IsCoherentRetryFixup (
+ IN STATE_DATA *State
+ );
+
+/**
+ * Find a specific HT capability type.
+ *
+ * @retval FALSE the capability was not found
+ */
+BOOLEAN
+DoesDeviceHaveHtSubtypeCap (
+ IN PCI_ADDR DevicePointer,
+ IN UINT8 CapSubType,
+ OUT PCI_ADDR *CapabilityBase,
+ IN STATE_DATA *State
+ );
+
+#endif /* _HT_FEAT_OPTIMIZATION_H_ */
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatRouting.c b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatRouting.c
new file mode 100644
index 0000000000..cad07435f0
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatRouting.c
@@ -0,0 +1,493 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Routing Routines
+ *
+ * Contains routines for isomorphic topology matching,
+ * routing determination, and routing initialization.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 35978 $ @e \$Date: 2010-08-07 02:18:50 +0800 (Sat, 07 Aug 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 "Topology.h"
+#include "htFeat.h"
+#include "htInterface.h"
+#include "htNotify.h"
+#include "htNb.h"
+#include "htGraph.h"
+#include "htFeatRouting.h"
+#include "htTopologies.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_HT_FEATURES_HTFEATROUTING_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+typedef struct {
+ UINT8 **CurrentPosition;
+ BOOLEAN IsCustomList;
+} TOPOLOGY_CONTEXT;
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/***************************************************************************
+ *** ISOMORPHISM BASED ROUTING TABLE GENERATION CODE ***
+ ***************************************************************************/
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Return the Link on source Node which connects to target Node
+ *
+ * @param[in] SourceNode The Node on which to find the Link
+ * @param[in] TargetNode The Link will connect to this Node
+ * @param[in] State Our global state
+ *
+ * @return the Link to target
+ */
+UINT8
+STATIC
+FindLinkToNode (
+ IN UINT8 SourceNode,
+ IN UINT8 TargetNode,
+ IN STATE_DATA *State
+ )
+{
+ UINT8 TargetLink;
+ UINT8 k;
+
+ // A node linked to itself is not a supported topology graph, this is probably an error in the
+ // topology data. There is not going to be a portlist match for it.
+ ASSERT (SourceNode != TargetNode);
+ TargetLink = INVALID_LINK;
+ for (k = 0; k < State->TotalLinks*2; k += 2) {
+ if (((*State->PortList)[k].NodeID == SourceNode) && ((*State->PortList)[k + 1].NodeID == TargetNode)) {
+ TargetLink = (*State->PortList)[k].Link;
+ break;
+ } else if (((*State->PortList)[k + 1].NodeID == SourceNode) && ((*State->PortList)[k].NodeID == TargetNode)) {
+ TargetLink = (*State->PortList)[k + 1].Link;
+ break;
+ }
+ }
+ ASSERT (TargetLink != INVALID_LINK);
+
+ return TargetLink;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Is graphA isomorphic to graphB?
+ *
+ * If this function returns true, then Perm will contain the permutation
+ * required to transform graphB into graphA.
+ * We also use the degree of each Node, that is the number of connections it has, to
+ * speed up rejection of non-isomorphic graphs (if there is a Node in graphA with n
+ * connections, there must be at least one unmatched in graphB with n connections).
+ *
+ * @param[in] Node the discovered Node which we are trying to match
+ * with a permutation the topology
+ * @param[in,out] State our global state, degree and adjacency matrix,
+ * output a permutation if successful
+ * @retval TRUE the graphs are isomorphic
+ * @retval FALSE the graphs are not isomorphic
+ *
+ */
+BOOLEAN
+STATIC
+IsIsomorphic (
+ IN UINT8 Node,
+ IN OUT STATE_DATA *State
+ )
+{
+ UINT8 j;
+ UINT8 k;
+ UINT8 Nodecnt;
+
+ // We have only been called if Nodecnt == pSelected->size !
+ Nodecnt = State->NodesDiscovered + 1;
+
+ if (Node != Nodecnt) {
+ // Keep building the permutation
+ for (j = 0; j < Nodecnt; j++) {
+ // Make sure the degree matches
+ if (State->Fabric->SysDegree[Node] != State->Fabric->DbDegree[j]) {
+ continue;
+ }
+
+ // Make sure that j hasn't been used yet (ought to use a "used"
+ // array instead, might be faster)
+ for (k = 0; k < Node; k++) {
+ if (State->Fabric->Perm[k] == j) {
+ break;
+ }
+ }
+ if (k != Node) {
+ continue;
+ }
+ State->Fabric->Perm[Node] = j;
+ if (IsIsomorphic (Node + 1, State)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } else {
+ // Test to see if the permutation is isomorphic
+ for (j = 0; j < Nodecnt; j++) {
+ for (k = 0; k < Nodecnt; k++) {
+ if (State->Fabric->SysMatrix[j][k] != State->Fabric->DbMatrix[State->Fabric->Perm[j]][State->Fabric->Perm[k]] ) {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Set Topology List iterator context to the Beginning and provide the first topology.
+ *
+ * Check the interface for a custom topology list. If one is found, set context to the
+ * first item, and return that item. Otherwise return the first item in the built in list.
+ *
+ * @param[in,out] TopologyContextHandle Initialize this context to beginning of lists.
+ * @param[out] NextTopology The next topology, NULL if end.
+ * @param[in] State Access to interface, handles.
+ *
+ */
+VOID
+STATIC
+BeginTopologies (
+ OUT TOPOLOGY_CONTEXT *TopologyContextHandle,
+ OUT UINT8 **NextTopology,
+ IN STATE_DATA *State
+ )
+{
+ if (State->HtBlock->Topolist != NULL) {
+ // Start with a custom list
+ TopologyContextHandle->CurrentPosition = State->HtBlock->Topolist;
+ TopologyContextHandle->IsCustomList = TRUE;
+ } else {
+ // Start with the built in list
+ GetAmdTopolist (&TopologyContextHandle->CurrentPosition);
+ TopologyContextHandle->IsCustomList = FALSE;
+ }
+ *NextTopology = *TopologyContextHandle->CurrentPosition;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Iterate through available topologies.
+ *
+ * Increment to the next list item. If we are doing a custom list, when we reach the end
+ * switch to the built in list.
+ *
+ * @param[in,out] TopologyContextHandle Maintain iterator's context from one call to the next
+ * @param[out] NextTopology The next topology, NULL if end.
+ *
+ */
+VOID
+STATIC
+GetNextTopology (
+ IN OUT TOPOLOGY_CONTEXT *TopologyContextHandle,
+ OUT UINT8 **NextTopology
+ )
+{
+ // Not valid to continue calling this routine after reaching the end.
+ ASSERT (TopologyContextHandle->CurrentPosition != NULL);
+
+ if (TopologyContextHandle->IsCustomList) {
+ // We are iterating the custom list from the interface.
+ TopologyContextHandle->CurrentPosition++;
+ if (*TopologyContextHandle->CurrentPosition == NULL) {
+ // We are at the end of the custom list, switch to the built in list.
+ TopologyContextHandle->IsCustomList = FALSE;
+ GetAmdTopolist (&TopologyContextHandle->CurrentPosition);
+ }
+ } else {
+ // We are iterating the built in list
+ TopologyContextHandle->CurrentPosition++;
+ // If we are at the end of the built in list, NextTopology == NULL is the AtEnd.
+ }
+ *NextTopology = *TopologyContextHandle->CurrentPosition;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Using the description of the fabric topology we discovered, try to find a match
+ * among the supported topologies.
+ *
+ * @HtFeatMethod{::F_LOOKUP_COMPUTE_AND_LOAD_ROUTING_TABLES}
+ *
+ * A supported topology description matches the discovered fabric if the Nodes can be
+ * matched in such a way that all the Nodes connected in one set are exactly the
+ * Nodes connected in the other (formally, that the graphs are isomorphic). Which
+ * Links are used is not really important to matching. If the graphs match, then
+ * there is a permutation of one that translates the Node positions and Linkages to
+ * the other.
+ *
+ * In order to make the isomorphism test efficient, we test for matched number of Nodes
+ * (a 4 Node fabric is not isomorphic to a 2 Node topology), and provide degrees of Nodes
+ * to the isomorphism test.
+ *
+ * The generic routing table solution for any topology is predetermined and represented
+ * as part of the topology. The permutation we computed tells us how to interpret the
+ * routing onto the fabric we discovered. We do this working backward from the last
+ * Node discovered to the BSP, writing the routing tables as we go.
+ *
+ * @param[in,out] State the discovered fabric, degree matrix, permutation
+ *
+ */
+VOID
+LookupComputeAndLoadRoutingTables (
+ IN OUT STATE_DATA *State
+ )
+{
+ TOPOLOGY_CONTEXT TopologyContextHandle;
+ UINT8 *Selected;
+ UINT8 Size;
+ UINT8 PairCounter;
+ UINT8 ReqTargetLink;
+ UINT8 RspTargetLink;
+ UINT8 ReqTargetNode;
+ UINT8 RspTargetNode;
+ UINT8 AbstractBcTargetNodes;
+ UINT32 BcTargetLinks;
+ UINT8 NodeCounter;
+ UINT8 NodeBeingRouted;
+ UINT8 NodeRoutedTo;
+ UINT8 BroadcastSourceNode;
+
+ Size = State->NodesDiscovered + 1;
+ BeginTopologies (&TopologyContextHandle, &Selected, State);
+ while (Selected != NULL) {
+ if (GraphHowManyNodes (Selected) == Size) {
+ // Build Degree vector and Adjacency Matrix for this entry
+ for (NodeCounter = 0; NodeCounter < Size; NodeCounter++) {
+ State->Fabric->DbDegree[NodeCounter] = 0;
+ for (PairCounter = 0; PairCounter < Size; PairCounter++) {
+ if (GraphIsAdjacent (Selected, NodeCounter, PairCounter)) {
+ State->Fabric->DbMatrix[NodeCounter][PairCounter] = TRUE;
+ State->Fabric->DbDegree[NodeCounter]++;
+ } else {
+ State->Fabric->DbMatrix[NodeCounter][PairCounter] = FALSE;
+ }
+ }
+ }
+
+ if (IsIsomorphic (0, State)) {
+ break; // A matching topology was found
+ }
+ }
+ GetNextTopology (&TopologyContextHandle, &Selected);
+ }
+
+ if (Selected != NULL) {
+ // Compute the reverse Permutation
+ for (NodeCounter = 0; NodeCounter < Size; NodeCounter++) {
+ State->Fabric->ReversePerm[State->Fabric->Perm[NodeCounter]] = NodeCounter;
+ }
+
+ // Start with the last discovered Node, and move towards the BSP
+ for (NodeCounter = 0; NodeCounter < Size; NodeCounter++) {
+ NodeBeingRouted = ((Size - 1) - NodeCounter);
+ for (NodeRoutedTo = 0; NodeRoutedTo < Size; NodeRoutedTo++) {
+ BcTargetLinks = 0;
+ AbstractBcTargetNodes = GraphGetBc (Selected, State->Fabric->Perm[NodeBeingRouted], State->Fabric->Perm[NodeRoutedTo]);
+
+ for (BroadcastSourceNode = 0; BroadcastSourceNode < MAX_NODES; BroadcastSourceNode++) {
+ if ((AbstractBcTargetNodes & ((UINT32)1 << BroadcastSourceNode)) != 0) {
+ // Accepting broadcast from yourself is handled in Nb, so in the topology graph it is an error.
+ ASSERT (NodeBeingRouted != State->Fabric->ReversePerm[BroadcastSourceNode]);
+ BcTargetLinks |= (UINT32)1 << FindLinkToNode (NodeBeingRouted, State->Fabric->ReversePerm[BroadcastSourceNode], State);
+ }
+ }
+
+ if (NodeBeingRouted == NodeRoutedTo) {
+ ReqTargetLink = ROUTE_TO_SELF;
+ RspTargetLink = ROUTE_TO_SELF;
+ } else {
+ ReqTargetNode = GraphGetReq (Selected, State->Fabric->Perm[NodeBeingRouted], State->Fabric->Perm[NodeRoutedTo]);
+ ReqTargetLink = FindLinkToNode (NodeBeingRouted, State->Fabric->ReversePerm[ReqTargetNode], State);
+
+ RspTargetNode = GraphGetRsp (Selected, State->Fabric->Perm[NodeBeingRouted], State->Fabric->Perm[NodeRoutedTo]);
+ RspTargetLink = FindLinkToNode (NodeBeingRouted, State->Fabric->ReversePerm[RspTargetNode], State);
+ }
+ State->Nb->WriteFullRoutingTable (NodeBeingRouted, NodeRoutedTo, ReqTargetLink, RspTargetLink, BcTargetLinks, State->Nb);
+ }
+ // Clean up discovery 'footprint' that otherwise remains in the routing table. It didn't hurt
+ // anything, but might cause confusion during debug and validation. Do this by setting the
+ // route back to all self routes. Since it's the Node that would be one more than actually installed,
+ // this only applies if less than MaxNodes were found.
+ //
+ if (Size < MAX_NODES) {
+ State->Nb->WriteFullRoutingTable (NodeBeingRouted, Size, ROUTE_TO_SELF, ROUTE_TO_SELF, 0, State->Nb);
+ }
+ }
+ } else {
+ //
+ // No Matching Topology was found
+ // Error Strategy:
+ // Auto recovery doesn't seem likely, Force boot as 1P.
+ // For reporting, logging, provide number of Nodes
+ // If not implemented or returns, boot as BSP uniprocessor.
+ //
+ // This can be caused by not supplying an additional topology list, if your board is not one of the built-in topologies.
+ //
+ NotifyErrorCohNoTopology (State->NodesDiscovered, State);
+ IDS_ERROR_TRAP;
+ // Force 1P
+ State->NodesDiscovered = 0;
+ State->TotalLinks = 0;
+ State->Nb->EnableRoutingTables (0, State->Nb);
+ State->HtInterface->CleanMapsAfterError (State);
+ }
+ // Save the topology pointer, or NULL, for other features
+ State->Fabric->MatchedTopology = Selected;
+ IDS_HDT_CONSOLE (
+ HT_TRACE,
+ "System routed as %s.\n",
+ ((TopologyContextHandle.IsCustomList) ?
+ "custom topology" :
+ (((Selected == amdHtTopologySingleNode) || (Selected == NULL)) ?
+ "single node" :
+ ((Selected == amdHtTopologyDualNode) ?
+ "dual node" :
+ ((Selected == amdHtTopologyFourSquare) ?
+ "four node box" :
+ ((Selected == amdHtTopologyFourKite) ?
+ "four node kite" :
+ ((Selected == amdHtTopologyFourFully) ?
+ "fully connected four-way" :
+ ((Selected == amdHtTopologyEightDoubloon) ?
+ "MCM max performance" :
+ ((Selected == amdHtTopologyEightTwinFullyFourWays) ?
+ "MCM max I/O" :
+ "AMD builtin topology"))))))))
+ );
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Make a Hop Count Table for the installed topology.
+ *
+ * @HtFeatMethod{::F_MAKE_HOP_COUNT_TABLE}
+ *
+ * For SLIT, create a node x node matrix with the number of hops. We can do this
+ * using the topology and the permutation, counting the nodes visited in the routes between
+ * nodes.
+ *
+ * @param[in,out] State access topology, permutation, update hop table
+ *
+ */
+VOID
+MakeHopCountTable (
+ IN OUT STATE_DATA *State
+ )
+{
+ UINT8 Origin;
+ UINT8 Target;
+ UINT8 Current;
+ UINT8 Hops;
+ UINT8 Size;
+
+ ASSERT (State->Fabric != NULL);
+ if (State->HopCountTable != NULL) {
+ if (State->Fabric->MatchedTopology != NULL) {
+ Size = GraphHowManyNodes (State->Fabric->MatchedTopology);
+ State->HopCountTable->Size = Size;
+ //
+ // For each node, targeting each node, follow the request path through the database graph,
+ // counting the number of edges.
+ //
+ for (Origin = 0; Origin < Size; Origin++) {
+ for (Target = 0; Target < Size; Target++) {
+ // If both nodes are the same the answer will be zero
+ Hops = 0;
+ // Current starts as the database node corresponding to system node Origin.
+ Current = State->Fabric->Perm[Origin];
+ // Stop if Current is the database node corresponding to system node Target
+ while (Current != State->Fabric->Perm[Target]) {
+ // This is a hop, so count it. Move Current to the next intermediate database node.
+ Hops++;
+ Current = GraphGetReq (State->Fabric->MatchedTopology, Current, State->Fabric->Perm[Target]);
+ }
+ // Put the hop count in the table.
+ State->HopCountTable->Hops[ ((Origin * Size) + Target)] = Hops;
+ }
+ }
+ }
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatRouting.h b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatRouting.h
new file mode 100644
index 0000000000..264434b5b2
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatRouting.h
@@ -0,0 +1,90 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Routing Feature Interface.
+ *
+ * Interfaces to routing and isomorphism routines.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 34897 $ @e \$Date: 2010-07-14 10:07:10 +0800 (Wed, 14 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.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _HT_FEAT_ROUTING_H_
+#define _HT_FEAT_ROUTING_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/**
+ * Using the description of the fabric topology we discovered, try to find a match
+ * among the supported topologies.
+ *
+ */
+VOID
+LookupComputeAndLoadRoutingTables (
+ IN OUT STATE_DATA *State
+ );
+
+/**
+ * Make a Hop Count Table for the installed topology.
+ *
+ */
+VOID
+MakeHopCountTable (
+ IN OUT STATE_DATA *State
+ );
+
+#endif /* _HT_FEAT_ROUTING_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSets.c b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSets.c
new file mode 100644
index 0000000000..ec2f164646
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSets.c
@@ -0,0 +1,114 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * HyperTransport feature sets initializers.
+ *
+ * @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 "OptionsHt.h"
+#include "Ids.h"
+#include "Topology.h"
+#include "htFeat.h"
+#include "CommonReturns.h"
+#include "htFeatDynamicDiscovery.h"
+#include "htFeatRouting.h"
+#include "htFeatNoncoherent.h"
+#include "htFeatOptimization.h"
+#include "htFeatGanging.h"
+#include "htFeatSublinks.h"
+#include "htFeatTrafficDistribution.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_HT_FEATURES_HTFEATSETS_FILECODE
+extern CONST OPTION_HT_CONFIGURATION OptionHtConfiguration;
+
+/**
+ * Initializer for the default feature set implementation,
+ * full features.
+ */
+CONST HT_FEATURES ROMDATA HtFeaturesDefault =
+{
+ CoherentDiscovery,
+ LookupComputeAndLoadRoutingTables,
+ MakeHopCountTable,
+ ProcessLink,
+ GatherLinkData,
+ SelectOptimalWidthAndFrequency,
+ RegangLinks,
+ SubLinkRatioFixup,
+ IsCoherentRetryFixup,
+ SetLinkData,
+ TrafficDistribution,
+ SetHtControlRegisterBits,
+ ConvertWidthToBits
+};
+
+/**
+ * Initializer for the non-coherent only build option.
+ */
+CONST HT_FEATURES ROMDATA HtFeaturesNonCoherentOnly =
+{
+ (PF_COHERENT_DISCOVERY)CommonVoid,
+ (PF_LOOKUP_COMPUTE_AND_LOAD_ROUTING_TABLES)CommonVoid,
+ (PF_MAKE_HOP_COUNT_TABLE)CommonVoid,
+ ProcessLink,
+ GatherLinkData,
+ SelectOptimalWidthAndFrequency,
+ (PF_REGANG_LINKS)CommonVoid,
+ (PF_SUBLINK_RATIO_FIXUP)CommonVoid,
+ (PF_IS_COHERENT_RETRY_FIXUP)CommonReturnFalse,
+ SetLinkData,
+ (PF_TRAFFIC_DISTRIBUTION)CommonVoid,
+ SetHtControlRegisterBits,
+ ConvertWidthToBits
+};
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
+}
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.h b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.h
new file mode 100644
index 0000000000..864dfb516e
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatSublinks.h
@@ -0,0 +1,80 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * SubLink Interface.
+ *
+ * Contains interface to subLink management feature, for unganged subLinks.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 34897 $ @e \$Date: 2010-07-14 10:07:10 +0800 (Wed, 14 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.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _HT_FEAT_SUBLINKS_H_
+#define _HT_FEAT_SUBLINKS_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/**
+ * Iterate through all Links, checking the frequency of each subLink pair.
+ *
+ */
+VOID
+SubLinkRatioFixup (
+ IN OUT STATE_DATA *State
+ );
+
+#endif /* _HT_FEAT_SUBLINKS_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatTrafficDistribution.c b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatTrafficDistribution.c
new file mode 100644
index 0000000000..05135784c1
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatTrafficDistribution.c
@@ -0,0 +1,278 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Traffic Distribution Routines.
+ *
+ * Contains routines for traffic distribution
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 35978 $ @e \$Date: 2010-08-07 02:18:50 +0800 (Sat, 07 Aug 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 "htNotify.h"
+#include "htFeatTrafficDistribution.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_HT_FEATURES_HTFEATTRAFFICDISTRIBUTION_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Identify Links which can have traffic distribution.
+ *
+ * @HtFeatMethod{::F_TRAFFIC_DISTRIBUTION}
+ *
+ * If there are redundant links between any nodes, traffic distribution allows the
+ * redundant links to be used to improve performance.
+ *
+ * There are two types of traffic distribution. Their use is mutually exclusive, both
+ * can not be used at once.
+ *
+ * Coherent Traffic Distribution is for systems of exactly two nodes only. All links must
+ * be symmetrical (the same width). As many links as are connected can be distributed over.
+ *
+ * Link Pair Traffic Distribution works with redundant pairs of links between any two nodes,
+ * it does not matter how many nodes are in the system or how many have a redundant link pair.
+ * A node can have redundant link pairs with more than one other node.
+ * The link pair can be asymmetric, the largest link must be used as the master. However,
+ * between any pair of nodes there is only one pair of redundant links, and there is a limit
+ * to the total number of pairs each node can have. So not all links will necessarily be
+ * made usable.
+ *
+ * @param[in] State port list data
+ */
+VOID
+TrafficDistribution (
+ IN STATE_DATA *State
+ )
+{
+ UINT32 Links01;
+ UINT32 Links10;
+ UINT8 LinkCount;
+ UINT8 i;
+ UINT8 LastLink;
+ BOOLEAN IsAsymmetric;
+ UINT8 RedundantLinkCount[MAX_NODES][MAX_NODES];
+ UINT8 MasterLinkPort[MAX_NODES][MAX_NODES];
+ UINT8 AlternateLinkPort[MAX_NODES][MAX_NODES];
+ UINT8 NodeA;
+ UINT8 NodeB;
+ UINT8 PairCount;
+
+ LastLink = 0xFF;
+ IsAsymmetric = FALSE;
+
+ // Traffic Distribution is only used when there are exactly two Nodes in the system
+ // and when all the links are symmetric, same width.
+ if ((State->NodesDiscovered + 1) == 2) {
+ Links01 = 0;
+ Links10 = 0;
+ LinkCount = 0;
+ for (i = 0; i < (State->TotalLinks * 2); i += 2) {
+ if (((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) &&
+ ((*State->PortList)[i + 1].Type == PORTLIST_TYPE_CPU)) {
+ if ((LastLink != 0xFF) &&
+ ((*State->PortList)[i].SelWidthOut != (*State->PortList)[LastLink].SelWidthOut) &&
+ ((*State->PortList)[i + 1].SelWidthOut != (*State->PortList)[LastLink + 1].SelWidthOut)) {
+ IsAsymmetric = TRUE;
+ break;
+ }
+ Links01 |= (UINT32)1 << (*State->PortList)[i].Link;
+ Links10 |= (UINT32)1 << (*State->PortList)[i + 1].Link;
+ LinkCount++;
+ LastLink = i;
+ }
+ }
+ ASSERT (LinkCount != 0);
+ // Don't setup Traffic Distribution if only one Link is being used or there were asymmetric widths
+ if ((LinkCount != 1) && !IsAsymmetric) {
+ IDS_HDT_CONSOLE (HT_TRACE, "Applying coherent traffic distribution.\n");
+ State->Nb->WriteTrafficDistribution (Links01, Links10, State->Nb);
+ // If we did Traffic Distribution, we must not do Link Pair, so get out of here.
+ return;
+ }
+ }
+ // Either there are more than two nodes, Asymmetric links, or no redundant links.
+ // See if we can use Link Pair Traffic Distribution
+ LibAmdMemFill (&RedundantLinkCount, 0, (MAX_NODES * MAX_NODES), State->ConfigHandle);
+ for (i = 0; i < (State->TotalLinks * 2); i += 2) {
+ if (((*State->PortList)[i].Type == PORTLIST_TYPE_CPU) &&
+ ((*State->PortList)[i + 1].Type == PORTLIST_TYPE_CPU)) {
+ NodeA = (*State->PortList)[i].NodeID;
+ NodeB = (*State->PortList)[i + 1].NodeID;
+ if (RedundantLinkCount[NodeA][NodeB] == 0) {
+ // This is the first link connecting two nodes
+ ASSERT (RedundantLinkCount[NodeB][NodeA] == 0);
+ MasterLinkPort[NodeA][NodeB] = i;
+ MasterLinkPort[NodeB][NodeA] = i + 1;
+ } else {
+ // This is a redundant link. If it is larger than the current master link,
+ // make it the new master link.
+ //
+ if (((*State->PortList)[MasterLinkPort[NodeA][NodeB]].SelWidthOut < (*State->PortList)[i].SelWidthOut) &&
+ ((*State->PortList)[MasterLinkPort[NodeB][NodeA]].SelWidthOut < (*State->PortList)[i + 1].SelWidthOut)) {
+ // Make the old master link the alternate, we don't need to check, it is bigger.
+ AlternateLinkPort[NodeA][NodeB] = MasterLinkPort[NodeA][NodeB];
+ AlternateLinkPort[NodeB][NodeA] = MasterLinkPort[NodeB][NodeA];
+ MasterLinkPort[NodeA][NodeB] = i;
+ MasterLinkPort[NodeB][NodeA] = i + 1;
+ } else {
+ // Since the new link isn't bigger than the Master, check if it is bigger than the alternate,
+ // if we have an alternate. If we don't have an alternate yet, make this link the alternate.
+ if (RedundantLinkCount[NodeA][NodeB] == 1) {
+ AlternateLinkPort[NodeA][NodeB] = i;
+ AlternateLinkPort[NodeB][NodeA] = i + 1;
+ } else {
+ if (((*State->PortList)[AlternateLinkPort[NodeA][NodeB]].SelWidthOut < (*State->PortList)[i].SelWidthOut) &&
+ ((*State->PortList)[AlternateLinkPort[NodeB][NodeA]].SelWidthOut < (*State->PortList)[i + 1].SelWidthOut)) {
+ // Warning: the alternate link is an unusable redundant link
+ // Then make the new link the alternate link.
+ NotifyWarningOptUnusedLinks (
+ NodeA,
+ (*State->PortList)[AlternateLinkPort[NodeA][NodeB]].Link,
+ NodeB,
+ (*State->PortList)[AlternateLinkPort[NodeB][NodeA]].Link,
+ State
+ );
+ ASSERT (RedundantLinkCount[NodeB][NodeA] > 1);
+ AlternateLinkPort[NodeA][NodeB] = i;
+ AlternateLinkPort[NodeB][NodeA] = i + 1;
+ } else {
+ // Warning the current link is an unusable redundant link
+ NotifyWarningOptUnusedLinks (NodeA, (*State->PortList)[i].Link, NodeB, (*State->PortList)[i].Link, State);
+ }
+ }
+ }
+ }
+ RedundantLinkCount[NodeA][NodeB]++;
+ RedundantLinkCount[NodeB][NodeA]++;
+ }
+ }
+ // If we found any, now apply up to 4 per node
+ for (NodeA = 0; NodeA < MAX_NODES; NodeA++) {
+ PairCount = 0;
+ for (NodeB = 0; NodeB < MAX_NODES; NodeB++) {
+ if (RedundantLinkCount[NodeA][NodeB] > 1) {
+ // Then there is a pair of links (at least, but we only care about the pair not the extras)
+ if (PairCount < MAX_LINK_PAIRS) {
+ // Program it
+ if ((*State->PortList)[MasterLinkPort[NodeA][NodeB]].SelWidthOut
+ != (*State->PortList)[AlternateLinkPort[NodeA][NodeB]].SelWidthOut) {
+ IsAsymmetric = TRUE;
+ } else {
+ IsAsymmetric = FALSE;
+ }
+ State->Nb->WriteLinkPairDistribution (
+ NodeA,
+ NodeB,
+ PairCount,
+ IsAsymmetric,
+ (*State->PortList)[MasterLinkPort[NodeA][NodeB]].Link,
+ (*State->PortList)[AlternateLinkPort[NodeA][NodeB]].Link,
+ State->Nb
+ );
+ PairCount++;
+ } else {
+ // Warning: More link pairs than can be distributed
+ NotifyWarningOptLinkPairExceed (
+ NodeA, NodeB,
+ (*State->PortList)[MasterLinkPort[NodeA][NodeB]].Link,
+ (*State->PortList)[AlternateLinkPort[NodeA][NodeB]].Link,
+ State);
+ // Disable the link pair from the other node, the analysis loop made sure there
+ // can only be a single link pair between a pair of nodes.
+ RedundantLinkCount[NodeB][NodeA] = 1;
+ }
+ }
+ }
+ IDS_HDT_CONSOLE (
+ HT_TRACE,
+ ((PairCount != 0) ?
+ "Node %d applying %d link pair distributions.\n" :
+ ""),
+ NodeA,
+ PairCount
+ );
+ }
+}
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatTrafficDistribution.h b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatTrafficDistribution.h
new file mode 100644
index 0000000000..963435f16f
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htFeatTrafficDistribution.h
@@ -0,0 +1,79 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Traffic Distribution Interface.
+ *
+ * Interface to traffic distribution feature.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: HyperTransport
+ * @e \$Revision: 34897 $ @e \$Date: 2010-07-14 10:07:10 +0800 (Wed, 14 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.
+ *
+ * ***************************************************************************
+ *
+ */
+
+#ifndef _HT_FEAT_TRAFFIC_DISTRIBUTION_H_
+#define _H_TFEAT_TRAFFIC_DISTRIBUTION_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+/**
+ * Identify Links which can have traffic distribution.
+ *
+ */
+VOID
+TrafficDistribution (
+ IN STATE_DATA *State
+ );
+
+#endif /* _HT_FEAT_TRAFFIC_DISTRIBUTION_H_ */
+
+
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htIds.c b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htIds.c
new file mode 100644
index 0000000000..6820824cc9
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/Features/htIds.c
@@ -0,0 +1,153 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD IDS HyperTransport Implementation.
+ *
+ * Contains AMD AGESA Integrated Debug HT related support.
+ *
+ * @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.
+ *
+ * ***************************************************************************
+ *
+ */
+
+
+#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 "htNb.h"
+#include "heapManager.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+#define FILECODE PROC_HT_FEATURES_HTIDS_FILECODE
+
+
+/*-------------------------------------------------------------------------------------*/
+/**
+ * Apply an IDS port override to the desired HT link.
+ *
+ * The IDS port override allows absolute control of a link's frequency and width, such as
+ * would be used for board characterization and test. The IDS backend code is responsible
+ * for handling the NV items and building them into a port override list. Here we search
+ * that list for any overrides which apply, and update the data used by the HT feature code.
+ *
+ * @param[in] IsSourcePort Since we handle both ports on a match, only do that if TRUE.
+ * @param[in,out] Port0 The PORTLIST item for the first endpoint of a link.
+ * @param[in,out] Port1 The PORTLIST item for the second endpoint of a link.
+ * @param[in,out] PortOverrideList IN: A pointer to the port override list or NULL,
+ * OUT: A pointer to the port override list.
+ * @param[in] State access to ht interface and nb support methods.
+ *
+ */
+VOID
+HtIdsGetPortOverride (
+ IN BOOLEAN IsSourcePort,
+ IN OUT PORT_DESCRIPTOR *Port0,
+ IN OUT PORT_DESCRIPTOR *Port1,
+ IN OUT HTIDS_PORT_OVERRIDE_LIST *PortOverrideList,
+ IN STATE_DATA *State
+ )
+{
+ LOCATE_HEAP_PTR LocHeapParams;
+ UINT8 SocketA;
+ UINT8 SocketB;
+ UINT8 PackageLinkA;
+ UINT8 PackageLinkB;
+ HTIDS_PORT_OVERRIDE_LIST p;
+
+ if (IsSourcePort) {
+ ASSERT (PortOverrideList != NULL);
+ // The caller can cache the override list by providing the pointer (to the heap buffer).
+ // If the pointer to the port override list is null, then check if it is on the heap,
+ // and update the caller's pointer so it is cached.
+ // If the buffer is not in heap, call the IDS backend to get the NV data (which is likely also
+ // in heap).
+ if (*PortOverrideList == NULL) {
+ // locate the table in heap
+ LocHeapParams.BufferHandle = IDS_HT_DATA_HANDLE;
+ if (HeapLocateBuffer (&LocHeapParams, State->ConfigHandle) == AGESA_SUCCESS) {
+ *PortOverrideList = (HTIDS_PORT_OVERRIDE_LIST)LocHeapParams.BufferPtr;
+ } else {
+ // Ask IDS backend code for the list
+ IDS_OPTION_HOOK (IDS_HT_CONTROL, PortOverrideList, State->ConfigHandle);
+ }
+ }
+ ASSERT (*PortOverrideList != NULL);
+
+ // Search the port override list to see if there is an override that applies to this link.
+ // The match criteria are if either endpoint of the current port list item matches
+ // port override.
+ p = *PortOverrideList;
+ SocketA = State->HtInterface->GetSocketFromMap (Port0->NodeID, State);
+ PackageLinkA = State->Nb->GetPackageLink (Port0->NodeID, Port0->Link, State->Nb);
+ SocketB = State->HtInterface->GetSocketFromMap (Port1->NodeID, State);
+ PackageLinkB = State->Nb->GetPackageLink (Port1->NodeID, Port1->Link, State->Nb);
+
+ while ((p != NULL) && (p->Socket != HT_LIST_TERMINAL)) {
+ if (((p->Socket == SocketA) || (p->Socket == HT_LIST_MATCH_ANY)) &&
+ ((p->Link == PackageLinkA) ||
+ ((p->Link == HT_LIST_MATCH_ANY) && (!IsPackageLinkInternal (PackageLinkA))) ||
+ ((p->Link == HT_LIST_MATCH_INTERNAL_LINK) && (IsPackageLinkInternal (PackageLinkA)))) ||
+ ((p->Socket == SocketB) || (p->Socket == HT_LIST_MATCH_ANY)) &&
+ ((p->Link == PackageLinkB) ||
+ ((p->Link == HT_LIST_MATCH_ANY) && (!IsPackageLinkInternal (PackageLinkA))) ||
+ ((p->Link == HT_LIST_MATCH_INTERNAL_LINK) && (IsPackageLinkInternal (PackageLinkB))))) {
+ // Found a match, update width and frequency of both endpoints.
+ if (p->WidthIn != HT_LIST_TERMINAL) {
+ Port0->SelWidthIn = p->WidthIn;
+ Port1->SelWidthOut = p->WidthIn;
+ }
+ if (p->WidthOut != HT_LIST_TERMINAL) {
+ Port0->SelWidthOut = p->WidthOut;
+ Port1->SelWidthIn = p->WidthOut;
+ }
+ if (p->Frequency != HT_LIST_TERMINAL) {
+ Port0->SelFrequency = p->Frequency;
+ Port1->SelFrequency = p->Frequency;
+ }
+ break;
+ } else {
+ p++;
+ }
+ }
+ }
+}
+