summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f14/Proc/HT/NbCommon/htNbCoherent.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f14/Proc/HT/NbCommon/htNbCoherent.c')
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/HT/NbCommon/htNbCoherent.c492
1 files changed, 492 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f14/Proc/HT/NbCommon/htNbCoherent.c b/src/vendorcode/amd/agesa/f14/Proc/HT/NbCommon/htNbCoherent.c
new file mode 100644
index 0000000000..d1e923f673
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/HT/NbCommon/htNbCoherent.c
@@ -0,0 +1,492 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Coherent Feature Northbridge routines.
+ *
+ * Provide access to hardware for routing, coherent discovery.
+ *
+ * @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 "htNb.h"
+#include "htNbHardwareFam10.h"
+#include "htNbCoherent.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_HT_NBCOMMON_HTNBCOHERENT_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/***************************************************************************
+ *** FAMILY/NORTHBRIDGE SPECIFIC FUNCTIONS ***
+ ***************************************************************************/
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Establish a Temporary route from one Node to another.
+ *
+ * @HtNbMethod{::F_WRITE_ROUTING_TABLE}
+ *
+ * This routine will modify the routing tables on the
+ * SourceNode to cause it to route both request and response traffic to the
+ * targetNode through the specified Link.
+ *
+ * @note: This routine is to be used for early discovery and initialization. The
+ * final routing tables must be loaded some other way because this
+ * routine does not address the issue of probes, or independent request
+ * response paths.
+ *
+ * @param[in] Node the Node that will have it's routing tables modified.
+ * @param[in] Target For routing to Node target
+ * @param[in] Link Link from Node to target
+ * @param[in] Nb this northbridge
+ */
+VOID
+WriteRoutingTable (
+ IN UINT8 Node,
+ IN UINT8 Target,
+ IN UINT8 Link,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ PCI_ADDR Reg;
+ UINT32 Temp;
+
+ ASSERT ((Node < MAX_NODES) && (Target < MAX_NODES) && (Link < Nb->MaxLinks));
+ Temp = (Nb->SelfRouteResponseMask | Nb->SelfRouteRequestMask) << (Link + 1);
+ Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+ MakePciBusFromNode (Node),
+ MakePciDeviceFromNode (Node),
+ CPU_HTNB_FUNC_00,
+ REG_ROUTE0_0X40 + (Target * 4));
+ LibAmdPciWrite (AccessWidth32, Reg, &Temp, Nb->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Modifies the NodeID register on the target Node
+ *
+ * @HtNbMethod{::F_WRITE_NODEID}
+ *
+ * @param[in] Node the Node that will have its NodeID altered.
+ * @param[in] NodeID the new value for NodeID
+ * @param[in] Nb this northbridge
+ */
+VOID
+WriteNodeID (
+ IN UINT8 Node,
+ IN UINT8 NodeID,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ PCI_ADDR Reg;
+ UINT32 Temp;
+ Temp = NodeID;
+ ASSERT ((Node < MAX_NODES) && (NodeID < MAX_NODES));
+ Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+ MakePciBusFromNode (Node),
+ MakePciDeviceFromNode (Node),
+ CPU_HTNB_FUNC_00,
+ REG_NODE_ID_0X60);
+ LibAmdPciWriteBits (Reg, 2, 0, &Temp, Nb->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Read the Default Link
+ *
+ * @HtNbMethod{::F_READ_DEFAULT_LINK}
+ *
+ * Read the DefLnk (the source Link of the current packet) from Node. Since this code
+ * is running on the BSP, this should be the Link pointing back towards the BSP.
+ *
+ * @param[in] Node the Node that will have its NodeID altered.
+ * @param[in] Nb this northbridge
+ *
+ * @return The HyperTransport Link where the request to
+ * read the default Link came from.
+ */
+UINT8
+ReadDefaultLink (
+ IN UINT8 Node,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ UINT32 DefaultLink;
+ PCI_ADDR Reg;
+ UINT32 Temp;
+
+ DefaultLink = 0;
+ Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+ MakePciBusFromNode (Node),
+ MakePciDeviceFromNode (Node),
+ CPU_HTNB_FUNC_00,
+ REG_LINK_INIT_CONTROL_0X6C);
+
+ ASSERT ((Node < MAX_NODES));
+ LibAmdPciReadBits (Reg, 3, 2, &DefaultLink, Nb->ConfigHandle);
+ LibAmdPciReadBits (Reg, 8, 8, &Temp, Nb->ConfigHandle);
+ DefaultLink |= (Temp << 2);
+ return (UINT8)DefaultLink;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Turns routing tables on for a given Node
+ *
+ * @HtNbMethod{::F_ENABLE_ROUTING_TABLES}
+ *
+ * @param[in] Node the Node that will have it's routing tables enabled
+ * @param[in] Nb this northbridge
+ */
+VOID
+EnableRoutingTables (
+ IN UINT8 Node,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ PCI_ADDR Reg;
+ UINT32 Temp;
+ Temp = 0;
+ ASSERT ((Node < MAX_NODES));
+ Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+ MakePciBusFromNode (Node),
+ MakePciDeviceFromNode (Node),
+ CPU_HTNB_FUNC_00,
+ REG_LINK_INIT_CONTROL_0X6C);
+ LibAmdPciWriteBits (Reg, 0, 0, &Temp, Nb->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Turns routing tables off for a given Node
+ *
+ * @HtNbMethod{::F_DISABLE_ROUTING_TABLES}
+ *
+ * @param[in] Node the Node that will have it's routing tables disabled
+ * @param[in] Nb this northbridge
+ */
+VOID
+DisableRoutingTables (
+ IN UINT8 Node,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ PCI_ADDR Reg;
+ UINT32 Temp;
+ Temp = 1;
+ ASSERT ((Node < MAX_NODES));
+ Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+ MakePciBusFromNode (Node),
+ MakePciDeviceFromNode (Node),
+ CPU_HTNB_FUNC_00,
+ REG_LINK_INIT_CONTROL_0X6C);
+ LibAmdPciWriteBits (Reg, 0, 0, &Temp, Nb->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Verify that the Link is coherent, connected, and ready
+ *
+ * @HtNbMethod{::F_VERIFY_LINK_IS_COHERENT}
+ *
+ * @param[in] Node the Node that will be examined
+ * @param[in] Link the Link on that Node to examine
+ * @param[in] Nb this northbridge
+ *
+ * @retval TRUE The Link has the following status
+ * - LinkCon=1, Link is connected
+ * - InitComplete=1, Link initialization is complete
+ * - NC=0, Link is coherent
+ * - UniP-cLDT=0, Link is not Uniprocessor cLDT
+ * - LinkConPend=0 Link connection is not pending
+ * @retval FALSE The Link has some other status
+*/
+BOOLEAN
+VerifyLinkIsCoherent (
+ IN UINT8 Node,
+ IN UINT8 Link,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ UINT32 LinkType;
+ PCI_ADDR LinkBase;
+
+ ASSERT ((Node < MAX_NODES) && (Link < Nb->MaxLinks));
+
+ LinkBase = Nb->MakeLinkBase (Node, Link, Nb);
+
+ // FN0_98/A4/C4 = LDT Type Register
+ LinkBase.Address.Register += HTHOST_LINK_TYPE_REG;
+ LibAmdPciRead (AccessWidth32, LinkBase, &LinkType, Nb->ConfigHandle);
+
+ // Verify LinkCon = 1, InitComplete = 1, NC = 0, UniP-cLDT = 0, LinkConPend = 0
+ return (BOOLEAN) ((LinkType & HTHOST_TYPE_MASK) == HTHOST_TYPE_COHERENT);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Read the token stored in the scratchpad register field.
+ *
+ * @HtNbMethod{::F_READ_TOKEN}
+ *
+ * Use the CPU core count as a scratch pad.
+ *
+ * @note The location used to store the token is arbitrary. The only requirement is
+ * that the location warm resets to zero, and that using it will have no ill-effects
+ * during HyperTransport initialization.
+ *
+ * @param[in] Node the Node that will be examined
+ * @param[in] Nb this northbridge
+ *
+ * @return the Token read from the Node
+ */
+UINT8
+ReadToken (
+ IN UINT8 Node,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ UINT32 Temp;
+ PCI_ADDR Reg;
+
+ ASSERT ((Node < MAX_NODES));
+ // Use CpuCnt as a scratch register
+ Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+ MakePciBusFromNode (Node),
+ MakePciDeviceFromNode (Node),
+ CPU_HTNB_FUNC_00,
+ REG_NODE_ID_0X60);
+ LibAmdPciReadBits (Reg, 19, 16, &Temp, Nb->ConfigHandle);
+
+ return (UINT8)Temp;
+}
+
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Write the token stored in the scratchpad register
+ *
+ * @HtNbMethod{::F_WRITE_TOKEN}
+ *
+ * Use the CPU core count as a scratch pad.
+ *
+ * @note The location used to store the token is arbitrary. The only requirement is
+ * that the location warm resets to zero, and that using it will have no ill-effects
+ * during HyperTransport initialization.
+ *
+ * @param[in] Node the Node that marked with token
+ * @param[in] Value the token Value
+ * @param[in] Nb this northbridge
+ */
+VOID
+WriteToken (
+ IN UINT8 Node,
+ IN UINT8 Value,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ PCI_ADDR Reg;
+ UINT32 Temp;
+ Temp = Value;
+ ASSERT ((Node < MAX_NODES));
+ // Use CpuCnt as a scratch register
+ Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+ MakePciBusFromNode (Node),
+ MakePciDeviceFromNode (Node),
+ CPU_HTNB_FUNC_00,
+ REG_NODE_ID_0X60);
+ LibAmdPciWriteBits (Reg, 19, 16, &Temp, Nb->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Full Routing Table Register initialization
+ *
+ * @HtNbMethod{::F_WRITE_FULL_ROUTING_TABLE}
+ *
+ * Write the routing table entry for Node to target, using the request Link, response
+ * Link, and broadcast Links provided.
+ *
+ * @param[in] Node the Node that will be examined
+ * @param[in] Target the Target Node for these routes
+ * @param[in] ReqLink the Link for requests to Target
+ * @param[in] RspLink the Link for responses to Target
+ * @param[in] BroadcastLinks the broadcast Links
+ * @param[in] Nb this northbridge
+ */
+VOID
+WriteFullRoutingTable (
+ IN UINT8 Node,
+ IN UINT8 Target,
+ IN UINT8 ReqLink,
+ IN UINT8 RspLink,
+ IN UINT32 BroadcastLinks,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ PCI_ADDR Reg;
+ UINT32 Value;
+
+ Value = 0;
+ ASSERT ((Node < MAX_NODES) && (Target < MAX_NODES));
+ if (ReqLink == ROUTE_TO_SELF) {
+ Value |= Nb->SelfRouteRequestMask;
+ } else {
+ Value |= Nb->SelfRouteRequestMask << (ReqLink + 1);
+ }
+
+ if (RspLink == ROUTE_TO_SELF) {
+ Value |= Nb->SelfRouteResponseMask;
+ } else {
+ Value |= Nb->SelfRouteResponseMask << (RspLink + 1);
+ }
+
+ // Allow us to accept a Broadcast ourselves, then set broadcasts for routes
+ Value |= (UINT32)1 << Nb->BroadcastSelfBit;
+ Value |= (UINT32)BroadcastLinks << (Nb->BroadcastSelfBit + 1);
+
+ Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+ MakePciBusFromNode (Node),
+ MakePciDeviceFromNode (Node),
+ CPU_HTNB_FUNC_00,
+ REG_ROUTE0_0X40 + (Target * 4));
+ LibAmdPciWrite (AccessWidth32, Reg, &Value, Nb->ConfigHandle);
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Determine whether a Node is compatible with the discovered configuration so far.
+ *
+ * @HtNbMethod{::F_IS_ILLEGAL_TYPE_MIX}.
+ *
+ * Currently, that means the family, extended family of the new Node are the
+ * same as the BSP's.
+ *
+ * @param[in] Node the Node
+ * @param[in] Nb this northbridge
+ *
+ * @retval TRUE the new node is not compatible
+ * @retval FALSE the new node is compatible
+ */
+BOOLEAN
+IsIllegalTypeMix (
+ IN UINT8 Node,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ return ((BOOLEAN) ((Nb->MakeKey (Node, Nb) & Nb->CompatibleKey) == 0));
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Fix (hopefully) exceptional conditions.
+ *
+ * @HtNbMethod{::F_HANDLE_SPECIAL_NODE_CASE}.
+ *
+ * Currently, this routine is implemented for all coherent HT families to check
+ * vendor ID of coherent Node. If the vendor ID is 0x1022 then return FALSE,
+ * or return TRUE.
+ *
+ * @param[in] Node The Node which need to be checked.
+ * @param[in] Link The link to check for special conditions.
+ * @param[in] State our global state.
+ * @param[in] Nb this northbridge.
+ *
+ * @retval TRUE This node received special handling.
+ * @retval FALSE This node was not handled specially, handle it normally.
+ *
+ */
+BOOLEAN
+HandleSpecialNodeCase (
+ IN UINT8 Node,
+ IN UINT8 Link,
+ IN STATE_DATA *State,
+ IN NORTHBRIDGE *Nb
+ )
+{
+ BOOLEAN Result;
+ PCI_ADDR Reg;
+ UINT32 VendorID;
+
+ Result = TRUE;
+
+ Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
+ MakePciBusFromNode (Node),
+ MakePciDeviceFromNode (Node),
+ 0,
+ 0);
+
+ LibAmdPciReadBits (Reg, 15, 0, &VendorID, Nb->ConfigHandle);
+ if (VendorID == 0x1022) {
+ Result = FALSE;
+ }
+
+ return Result;
+}