diff options
Diffstat (limited to 'src/vendorcode/amd/agesa/f15/Proc/HT/Fam10/htNbSystemFam10.c')
-rw-r--r-- | src/vendorcode/amd/agesa/f15/Proc/HT/Fam10/htNbSystemFam10.c | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f15/Proc/HT/Fam10/htNbSystemFam10.c b/src/vendorcode/amd/agesa/f15/Proc/HT/Fam10/htNbSystemFam10.c new file mode 100644 index 0000000000..ed921a2e43 --- /dev/null +++ b/src/vendorcode/amd/agesa/f15/Proc/HT/Fam10/htNbSystemFam10.c @@ -0,0 +1,402 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * System Tuning Family 10h specific routines + * + * Support for Traffic Distribution and buffer tunings which + * can not be done in a register table. + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: HyperTransport + * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $ + * + */ +/* +***************************************************************************** +* +* Copyright (C) 2012 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 "htNbCommonHardware.h" +#include "htNbSystemFam10.h" +#include "Filecode.h" +CODE_GROUP (G1_PEICC) +RDATA_GROUP (G2_PEI) + +#define FILECODE PROC_HT_FAM10_HTNBSYSTEMFAM10_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ +/** + * Register Fields for an individual link pair. + */ +typedef struct { + UINT32 Enable:1; ///< Enable distribution on this pair. + UINT32 Asymmetric:1; ///< Links are different widths. + UINT32 MasterSelect:3; ///< The master link. + UINT32 AlternateSelect:3; ///< The alternate link. +} PAIR_SELECT_FIELDS; + +/** + * Register access union for ::PAIR_SELECT_FIELDS. + */ +typedef union { + UINT32 Value; ///< access as a 32 bit value or register. + PAIR_SELECT_FIELDS Fields; ///< access individual fields. +} PAIR_SELECT; + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +/*************************************************************************** + *** FAMILY/NORTHBRIDGE SPECIFIC FUNCTIONS *** + ***************************************************************************/ + +/*----------------------------------------------------------------------------------------*/ +/** + * Set the traffic distribution register for the Links provided. + * + * @HtNbMethod{::F_WRITE_TRAFFIC_DISTRIBUTION} + * + * @param[in] Links01 coherent Links from Node 0 to 1 + * @param[in] Links10 coherent Links from Node 1 to 0 + * @param[in] Nb this northbridge + */ +VOID +Fam10WriteTrafficDistribution ( + IN UINT32 Links01, + IN UINT32 Links10, + IN NORTHBRIDGE *Nb + ) +{ + UINT32 Temp; + PCI_ADDR TrafficDistReg; + + TrafficDistReg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (0), + MakePciBusFromNode (0), + MakePciDeviceFromNode (0), + CPU_HTNB_FUNC_00, + REG_HT_TRAFFIC_DIST_0X164); + + // Node 0 + // DstLnk + LibAmdPciWriteBits (TrafficDistReg, 23, 16, &Links01, Nb->ConfigHandle); + // DstNode = 1, cHTPrbDistEn = 1, cHTRspDistEn = 1, cHTReqDistEn = 1 + Temp = 0x0107; + LibAmdPciWriteBits (TrafficDistReg, 15, 0, &Temp, Nb->ConfigHandle); + + TrafficDistReg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (1), + MakePciBusFromNode (1), + MakePciDeviceFromNode (1), + CPU_HTNB_FUNC_00, + REG_HT_TRAFFIC_DIST_0X164); + + // Node 1 + // DstLnk + LibAmdPciWriteBits (TrafficDistReg, 23, 16, &Links10, Nb->ConfigHandle); + // DstNode = 0, cHTPrbDistEn = 1, cHTRspDistEn = 1, cHTReqDistEn = 1 + Temp = 0x0007; + LibAmdPciWriteBits (TrafficDistReg, 15, 0, &Temp, Nb->ConfigHandle); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Write a link pair to the link pair distribution and fixups. + * + * @HtNbMethod{::F_WRITE_LINK_PAIR_DISTRIBUTION} + * + * Set the links as a pair using the link pair index provided. Set asymmetric attribute as + * provided. If the Master Link is not currently used as the route, fixup the routes for all + * nodes which specify the alternate link. + * + * @param[in] Node Set the pair on this node + * @param[in] ConnectedNode The Node to which this link pair directly connects. + * @param[in] Pair Using this pair set in the register + * @param[in] Asymmetric True if different widths + * @param[in] MasterLink Set this as the master link and in the route + * @param[in] AlternateLink Set this as the alternate link + * @param[in] Nb this northbridge + * + */ +VOID +Fam10WriteLinkPairDistribution ( + IN UINT8 Node, + IN UINT8 ConnectedNode, + IN UINT8 Pair, + IN BOOLEAN Asymmetric, + IN UINT8 MasterLink, + IN UINT8 AlternateLink, + IN NORTHBRIDGE *Nb + ) +{ + PCI_ADDR Reg; + UINT32 CurrentRoute; + UINT32 MasterRoute; + UINT32 AlternateRoute; + PAIR_SELECT Selection; + UINT32 RouteIndex; + + ASSERT ((Node < MAX_NODES) && (ConnectedNode < MAX_NODES)); + ASSERT (Pair < MAX_LINK_PAIRS); + ASSERT (MasterLink < Nb->MaxLinks); + ASSERT (AlternateLink < Nb->MaxLinks); + + // Make the master link the route for all routes to or through NodeB, by replacing all occurrences of + // Alternate link with Master link. If routing used the master link, no update is necessary. + MasterRoute = (((1 << Nb->BroadcastSelfBit) | Nb->SelfRouteResponseMask | Nb->SelfRouteRequestMask) << (MasterLink + 1)); + AlternateRoute = (((1 << Nb->BroadcastSelfBit) | Nb->SelfRouteResponseMask | Nb->SelfRouteRequestMask) << (AlternateLink + 1)); + Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), + MakePciBusFromNode (Node), + MakePciDeviceFromNode (Node), + CPU_HTNB_FUNC_00, + REG_ROUTE0_0X40); + for (RouteIndex = 0; RouteIndex < MAX_NODES; RouteIndex++) { + Reg.Address.Register = REG_ROUTE0_0X40 + (RouteIndex * 4); + LibAmdPciReadBits (Reg, 31, 0, &CurrentRoute, Nb->ConfigHandle); + if ((CurrentRoute & AlternateRoute) != 0) { + // Since Master and Alternate are redundant, the route must use one or the other but not both. + ASSERT ((CurrentRoute & MasterRoute) == 0); + // Set the master route for Request, Response or Broadcast only if the alternate was used for that case. + // Example, use of a link as a broadcast link is typically not the same route register as its use for Request, Response. + CurrentRoute = ((CurrentRoute & ~AlternateRoute) | + ((((CurrentRoute & AlternateRoute) >> (AlternateLink + 1)) << (MasterLink + 1)) & MasterRoute)); + LibAmdPciWriteBits (Reg, 31, 0, &CurrentRoute, Nb->ConfigHandle); + } + } + + // Set the Link Pair and Enable it + Selection.Fields.Enable = 1; + Selection.Fields.Asymmetric = Asymmetric; + Selection.Fields.MasterSelect = MasterLink; + Selection.Fields.AlternateSelect = AlternateLink; + Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), + MakePciBusFromNode (Node), + MakePciDeviceFromNode (Node), + CPU_HTNB_FUNC_00, + REG_HT_LINK_PAIR_DIST_0X1E0); + LibAmdPciWriteBits ( + Reg, + ((PAIR_SELECT_OFFSET * (Pair + 1)) - 1), + (PAIR_SELECT_OFFSET * Pair), + &Selection.Value, + Nb->ConfigHandle + ); +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Family 10h specific tunings. + * + * @HtNbMethod{::F_BUFFER_OPTIMIZATIONS} + * + * Buffer tunings are inherently northbridge specific. Check for specific configs + * which require adjustments and apply any standard workarounds to this Node. + * + * @param[in] Node the Node to tune + * @param[in] State global state + * @param[in] Nb this northbridge + */ +VOID +Fam10BufferOptimizations ( + IN UINT8 Node, + IN STATE_DATA *State, + IN NORTHBRIDGE *Nb + ) +{ + UINT32 Temp; + PCI_ADDR currentPtr; + PCI_ADDR GangedReg; + UINT8 i; + + ASSERT (Node < MAX_NODES); + + // + // Link to XCS Token Count Tuning + // + // For each active Link that we reganged (so this unfortunately can't go into the PCI reg + // table), we have to switch the Link to XCS Token Counts to the ganged state. + // We do this here for the non - uma case, which is to write the values that would have + // been power on defaults if the Link was ganged at cold reset. + // + for (i = 0; i < (State->TotalLinks * 2); i++) { + if (((*State->PortList)[i].NodeID == Node) && ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU)) { + // If the Link is greater than 4, this is a subLink 1, so it is not reganged. + if ((*State->PortList)[i].Link < 4) { + currentPtr.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), + MakePciBusFromNode (Node), + MakePciDeviceFromNode (Node), + CPU_NB_FUNC_03, + REG_NB_LINK_XCS_TOKEN0_3X148 + (4 * (*State->PortList)[i].Link) + ); + if ((*State->PortList)[i].SelRegang) { + // Handle all the regang Token count adjustments + + // SubLink 0: [Probe0tok] = 2 [Rsp0tok] = 2 [PReq0tok] = 2 [Req0tok] = 2 + Temp = 0xAA; + LibAmdPciWriteBits (currentPtr, 7, 0, &Temp, Nb->ConfigHandle); + // SubLink 1: [Probe1tok] = 0 [Rsp1tok] = 0 [PReq1tok] = 0 [Req1tok] = 0 + Temp = 0; + LibAmdPciWriteBits (currentPtr, 23, 16, &Temp, Nb->ConfigHandle); + // [FreeTok] = 3 + Temp = 3; + LibAmdPciWriteBits (currentPtr, 15, 14, &Temp, Nb->ConfigHandle); + + } else { + // Read the regang bit in hardware + GangedReg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode ((*State->PortList)[i].NodeID), + MakePciBusFromNode ((*State->PortList)[i].NodeID), + MakePciDeviceFromNode ((*State->PortList)[i].NodeID), + CPU_HTNB_FUNC_00, + REG_HT_LINK_EXT_CONTROL0_0X170 + (4 * (*State->PortList)[i].Link)); + LibAmdPciReadBits (GangedReg, 0, 0, &Temp, Nb->ConfigHandle); + if (Temp == 1) { + // handle a minor adjustment for strapped ganged Links. If SelRegang is false we + // didn't do the regang, so if the bit is on then it's hardware strapped. + // + + // [FreeTok] = 3 + Temp = 3; + LibAmdPciWriteBits (currentPtr, 15, 14, &Temp, Nb->ConfigHandle); + } + } + } + } + } +} + +/*----------------------------------------------------------------------------------------*/ +/** + * Family 10h specific tunings. + * + * @HtNbMethod{::F_BUFFER_OPTIMIZATIONS} + * + * Buffer tunings are inherently northbridge specific. Check for specific configs + * which require adjustments and apply any standard workarounds to this Node. + * + * @param[in] Node the Node to tune + * @param[in] State global state + * @param[in] Nb this northbridge + */ +VOID +Fam10RevDBufferOptimizations ( + IN UINT8 Node, + IN STATE_DATA *State, + IN NORTHBRIDGE *Nb + ) +{ + UINT32 Temp; + PCI_ADDR Reg; + UINT8 i; + FINAL_LINK_STATE FinalLinkState; + UINT32 WidthIn; + UINT32 WidthOut; + + ASSERT (Node < MAX_NODES); + + // + // Internal link fixup. + // When powering off internal link 2, a performance optimization may be possible where its buffers + // can be made available to the external paired sublink. If the conditions are met, do the fix up here. + // + for (i = 0; i < (State->TotalLinks * 2); i++) { + if (((*State->PortList)[i].NodeID == Node) && ((*State->PortList)[i].Type == PORTLIST_TYPE_CPU)) { + // Is this a sublink 0 paired with internal link 2? + if (((*State->PortList)[i].Link < 4) && + (Nb->GetPackageLink (Node, ((*State->PortList)[i].Link + 4), Nb) == HT_LIST_MATCH_INTERNAL_LINK_2)) { + FinalLinkState = State->HtInterface->GetIgnoreLink (Node, ((*State->PortList)[i].Link + 4), Nb->DefaultIgnoreLinkList, State); + // Are we ignoring the internal link 2 with Power Off? + if (FinalLinkState == POWERED_OFF) { + // Read the regang bit in hardware. + Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node), + MakePciBusFromNode (Node), + MakePciDeviceFromNode (Node), + CPU_HTNB_FUNC_00, + REG_HT_LINK_EXT_CONTROL0_0X170 + (4 * (*State->PortList)[i].Link)); + LibAmdPciReadBits (Reg, 0, 0, &Temp, Nb->ConfigHandle); + // If it's already ganged, skip to the width fix up. + if (Temp == 0) { + // Clear EndOfChain / XmitOff on internal sublink + Reg = Nb->MakeLinkBase (Node, ((*State->PortList)[i].Link + 4), Nb); + Reg.Address.Register += HTHOST_LINK_CONTROL_REG; + Temp = 0; + State->HtFeatures->SetHtControlRegisterBits (Reg, 7, 6, &Temp, State); + + // Gang the link + Nb->SetLinkRegang (Node, (*State->PortList)[i].Link, Nb); + } + + // Set InLnSt = PHY_OFF in register table. + // Set sublink 0 widths to 8 bits + if ((*State->PortList)[i].SelWidthOut > 8) { + (*State->PortList)[i].SelWidthOut = 8; + } + if ((*State->PortList)[i].SelWidthIn > 8) { + (*State->PortList)[i].SelWidthIn = 8; + } + WidthOut = State->HtFeatures->ConvertWidthToBits ((*State->PortList)[i].SelWidthOut); + WidthIn = State->HtFeatures->ConvertWidthToBits ((*State->PortList)[i].SelWidthIn); + Temp = (WidthIn & 7) | ((WidthOut & 7) << 4); + Reg = Nb->MakeLinkBase (Node, (*State->PortList)[i].Link, Nb); + Reg.Address.Register += HTHOST_LINK_CONTROL_REG; + State->HtFeatures->SetHtControlRegisterBits (Reg, 31, 24, &Temp, State); + } + } + } + } +} + |