diff options
Diffstat (limited to 'src/vendorcode/amd/agesa/f10/Proc/HT/NbCommon/htNbCoherent.c')
-rwxr-xr-x | src/vendorcode/amd/agesa/f10/Proc/HT/NbCommon/htNbCoherent.c | 488 |
1 files changed, 488 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f10/Proc/HT/NbCommon/htNbCoherent.c b/src/vendorcode/amd/agesa/f10/Proc/HT/NbCommon/htNbCoherent.c new file mode 100755 index 0000000000..18cee2db47 --- /dev/null +++ b/src/vendorcode/amd/agesa/f10/Proc/HT/NbCommon/htNbCoherent.c @@ -0,0 +1,488 @@ +/** + * @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: 44323 $ @e \$Date: 2010-12-22 01:24:58 -0700 (Wed, 22 Dec 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" +#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; +} |