示例#1
0
/**
 * Get Link features into system data structure.
 *
 * @HtNbMethod{::F_GATHER_LINK_FEATURES}
 *
 * For a specific discovered CPU Link, populate the port list with the frequency
 * capabilities.  Support for other link oriented capabilities, currently:
 * - Unit ID Clumping. Set to disabled. This doesn't mean the CPU doesn't support clumping,
 *   it just means:
 *   - The CPU doesn't clump its host unit ids, and
 *   - We don't have to check as carefully in SetLinkData whether the port is an IO host link.
 *
 * @param[in,out] ThisPort         The PortList structure entry for this link's port
 * @param[in]     Interface        Access to non-HT support functions.
 * @param[in]     PlatformConfig   Platform profile/build option config structure.
 * @param[in]     Nb               this northbridge
 */
VOID
GatherLinkFeatures (
  IN OUT   PORT_DESCRIPTOR        *ThisPort,
  IN       HT_INTERFACE           *Interface,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
  IN       NORTHBRIDGE            *Nb
  )
{
  PCI_ADDR Reg;
  UINT32 Frequency;
  UINT32 ExtendedFrequency;

  Reg = ThisPort->Pointer;
  Reg.Address.Register += HTHOST_FREQ_REV_REG;
  LibAmdPciReadBits (Reg, 30, 16, &Frequency, Nb->ConfigHandle);
  Reg = ThisPort->Pointer;
  Reg.Address.Register += HTHOST_FREQ_EXTENSION;
  LibAmdPciReadBits (Reg, 15, 1, &ExtendedFrequency, Nb->ConfigHandle);
  ThisPort->PrvFrequencyCap = ((Frequency | (ExtendedFrequency << HT_FREQUENCY_2800M)) &
                               Nb->NorthBridgeFreqMask (ThisPort->NodeID, Interface, PlatformConfig, Nb));
  // Check for Internal link restriction not to run at 1000 MHz (but allow lower)
  if (IsPackageLinkInternal (Nb->GetPackageLink (ThisPort->NodeID, ThisPort->Link, Nb))) {
    ThisPort->PrvFrequencyCap &= ~(HT_FREQUENCY_LIMIT_1000M & ~HT_FREQUENCY_LIMIT_800M);
  }
  ThisPort->ClumpingSupport = HT_CLUMPING_DISABLE;
}
示例#2
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;
}
示例#3
0
/**
 * Return whether the current configuration exceeds the capability.
 *
 * @HtNbMethod{::F_IS_EXCEEDED_CAPABLE}.
 *
 * Get Node capability and update the minimum supported system capability.
 *
 * @param[in]     Node     the Node
 * @param[in]     State    sysMpCap (updated) and NodesDiscovered
 * @param[in]     Nb       this northbridge
 *
 * @retval        TRUE     system is not capable of current config.
 * @retval        FALSE    system is capable of current config.
 */
BOOLEAN
Fam10IsExceededCapable (
  IN       UINT8       Node,
  IN       STATE_DATA  *State,
  IN       NORTHBRIDGE *Nb
  )
{
  UINT32 Temp;
  UINT8 MaxNodes;
  PCI_ADDR Reg;

  ASSERT (Node < MAX_NODES);

  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
                                 MakePciBusFromNode (Node),
                                 MakePciDeviceFromNode (Node),
                                 CPU_NB_FUNC_03,
                                 REG_NB_CAPABILITY_3XE8);

  LibAmdPciReadBits (Reg, 18, 16, &Temp, Nb->ConfigHandle);

  if (Temp != 0) {
    MaxNodes = (UINT8) (1 << (~Temp & 0x3));  // That is, 1, 2, 4, or 8
  } else {
    MaxNodes = 8;
  }
  if (State->SysMpCap > MaxNodes) {
    State->SysMpCap = MaxNodes;
  }
  // Note since sysMpCap is one based and NodesDiscovered is zero based, equal returns true
  //
  return ((BOOLEAN) (State->SysMpCap <= State->NodesDiscovered));
}
/**
 * Return the number of cores (1 based count) on Node.
 *
 * @HtNbMethod{::F_GET_NUM_CORES_ON_NODE}
 *
 * @param[in]     Node   the Node that will be examined
 * @param[in]     Nb     this northbridge
 *
 * @return        the number of cores
 */
UINT8
Fam15Mod1xGetNumCoresOnNode (
  IN       UINT8       Node,
  IN       NORTHBRIDGE *Nb
  )
{
  UINT32 Result;
  UINT32 Leveling;
  UINT32 Cores;
  UINT8 i;
  PCI_ADDR Reg;

  ASSERT ((Node < MAX_NODES));
  // Read CmpCap
  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
                                 MakePciBusFromNode (Node),
                                 MakePciDeviceFromNode (Node),
                                 CPU_NB_FUNC_05,
                                 REG_NB_CAPABILITY_2_5X84);

  LibAmdPciReadBits (Reg, 7, 0, &Result, Nb->ConfigHandle);

  // Support Downcoring
  Cores = Result;
  Cores++;
  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
                                 MakePciBusFromNode (Node),
                                 MakePciDeviceFromNode (Node),
                                 CPU_NB_FUNC_03,
                                 REG_NB_DOWNCORE_3X190);
  LibAmdPciReadBits (Reg, 31, 0, &Leveling, Nb->ConfigHandle);
  for (i = 0; i < Cores; i++) {
    if ((Leveling & ((UINT32) 1 << i)) != 0) {
      Result--;
    }
  }
  return (UINT8) (Result + 1);
}
示例#5
0
/**
 * 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;
}
示例#6
0
/**
 * Return the Link to the Southbridge
 *
 * @HtNbMethod{::F_READ_SB_LINK}
 *
 * @param[in] Nb this northbridge
 *
 * @return the Link to the southbridge
 */
UINT8
ReadSouthbridgeLink (
  IN       NORTHBRIDGE *Nb
  )
{
  UINT32 Temp;
  PCI_ADDR Reg;
  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (0),
                                 MakePciBusFromNode (0),
                                 MakePciDeviceFromNode (0),
                                 CPU_HTNB_FUNC_00,
                                 REG_UNIT_ID_0X64);
  LibAmdPciReadBits (Reg, 10, 8, &Temp, Nb->ConfigHandle);
  return (UINT8)Temp;
}
示例#7
0
/**
 * Get the quad core compute unit status for this node.
 *
 * @TopoNbMethod{::PF_GET_QUADCORE_COMPUTE_UNITS}
 *
 * @param[in]   Node    The node for which we want the quad core status
 * @param[in]   Nb      Our Northbridge.
 *
 * @return      The quad core compute unit status.
 */
UINT8
Fam16GetQuadcoreComputeUnits (
    IN       UINT8       Node,
    IN       NORTHBRIDGE *Nb
)
{
    UINT32 Quad;
    PCI_ADDR Reg;

    ASSERT ((Node < MAX_NODES));

    Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
                                   MakePciBusFromNode (Node),
                                   MakePciDeviceFromNode (Node),
                                   CPU_NB_FUNC_05,
                                   REG_NB_COMPUTE_UNIT_5X80);
    LibAmdPciReadBits (Reg, 27, 24, &Quad, Nb->ConfigHandle);
    return ((UINT8) Quad);
}
/**
 * Get the dual core compute unit status for this node.
 *
 * @HtNbMethod{::PF_GET_DUALCORE_COMPUTE_UNITS}
 *
 * @param[in]   Node    The node for which we want the dual core status
 * @param[in]   Nb      Our Northbridge.
 *
 * @return      The dual core compute unit status.
 */
UINT8
Fam15Mod1xGetDualcoreComputeUnits (
  IN       UINT8       Node,
  IN       NORTHBRIDGE *Nb
  )
{
  UINT32 Dual;
  PCI_ADDR Reg;

  ASSERT ((Node < MAX_NODES));

  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
                                 MakePciBusFromNode (Node),
                                 MakePciDeviceFromNode (Node),
                                 CPU_NB_FUNC_05,
                                 REG_NB_COMPUTE_UNIT_5X80);
  LibAmdPciReadBits (Reg, 17, 16, &Dual, Nb->ConfigHandle);
  return ((UINT8) Dual);
}
示例#9
0
/**
 * Construct a new northbridge.
 *
 * This routine encapsulates knowledge of how to tell significant differences between
 * families of supported northbridges and what routines can be used in common and
 * which are unique.  A fully populated northbridge interface is provided by Nb.
 *
 * @param[in]     Node    create a northbridge interface for this Node.
 * @param[in]     State   global state
 * @param[out]    Nb      the caller's northbridge structure to initialize.
 */
VOID
NewNorthBridge (
  IN       UINT8       Node,
  IN       STATE_DATA  *State,
     OUT   NORTHBRIDGE *Nb
  )
{
  CPU_LOGICAL_ID LogicalId;
  UINT64  Match;
  UINT32 RawCpuId;
  PCI_ADDR Reg;
  NORTHBRIDGE **InitializerInstance;

  // Start with enough of the key to identify the northbridge interface
  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
                                 MakePciBusFromNode (Node),
                                 MakePciDeviceFromNode (Node),
                                 CPU_NB_FUNC_03,
                                 REG_NB_CPUID_3XFC);
  LibAmdPciReadBits (Reg, 31, 0, &RawCpuId, State->ConfigHandle);
  IDS_HDT_CONSOLE (TOPO_TRACE, "AMD Processor at Node %d has raw CPUID=%x.\n", Node, RawCpuId);
  GetLogicalIdFromCpuid (RawCpuId, &LogicalId, State->ConfigHandle);
  Match = LogicalId.Family;

  // Test each Northbridge interface in turn looking for a match.
  // Use it to Init the Nb struct if a match is found.
  //
  ASSERT (OptionTopoConfiguration.TopoOptionFamilyNorthbridgeList != NULL);
  InitializerInstance = (NORTHBRIDGE **) (OptionTopoConfiguration.TopoOptionFamilyNorthbridgeList);
  while (*InitializerInstance != NULL) {
    if ((Match & (*InitializerInstance)->CompatibleKey) != 0) {
      LibAmdMemCopy ((VOID *)Nb, (VOID *)*InitializerInstance, (UINT32) sizeof (NORTHBRIDGE), State->ConfigHandle);
      break;
    }
    InitializerInstance++;
  }
  // There must be an available northbridge implementation.
  ASSERT (*InitializerInstance != NULL);

  // Set the config handle for passing to the library.
  Nb->ConfigHandle = State->ConfigHandle;
}
示例#10
0
/**
 * 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;
}
示例#11
0
/**
 * Make a compatibility key.
 *
 * @TopoNbMethod{::F_MAKE_KEY}
 *
 * Private routine to northbridge code.
 * Create a key which can be used to determine whether a Node is compatible with
 * the discovered configuration so far.  Currently, that means the family,
 * extended family of the new Node are the same as the BSP's.  Family specific
 * implementations can add whatever else is necessary.
 *
 * @param[in] Node the Node
 * @param[in] Nb   this northbridge
 *
 * @return the key
 */
UINT64
MakeKey (
  IN       UINT8 Node,
  IN       NORTHBRIDGE *Nb
  )
{
  CPU_LOGICAL_ID LogicalId;
  UINT32 RawCpuId;
  PCI_ADDR Reg;

  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
                                 MakePciBusFromNode (Node),
                                 MakePciDeviceFromNode (Node),
                                 CPU_NB_FUNC_03,
                                 REG_NB_CPUID_3XFC);

  LibAmdPciReadBits (Reg, 31, 0, &RawCpuId, Nb->ConfigHandle);
  GetLogicalIdFromCpuid (RawCpuId, &LogicalId, Nb->ConfigHandle);
  return LogicalId.Family;
}
示例#12
0
/**
 * Return the number of cores (1 based count) on Node.
 *
 * @HtNbMethod{::F_GET_NUM_CORES_ON_NODE}
 *
 * @param[in]     Node   the Node that will be examined
 * @param[in]     Nb     this northbridge
 *
 * @return        the number of cores
 */
UINT8
Fam12GetNumCoresOnNode (
  IN       UINT8       Node,
  IN       NORTHBRIDGE *Nb
  )
{
  UINT32 Cores;
  PCI_ADDR Reg;

  ASSERT ((Node < MAX_NODES));
  // Read CmpCap
  Reg.AddressValue = MAKE_SBDFO (MakePciSegmentFromNode (Node),
                                 MakePciBusFromNode (Node),
                                 MakePciDeviceFromNode (Node),
                                 CPU_NB_FUNC_03,
                                 REG_NB_CAPABILITY_3XE8);

  LibAmdPciReadBits (Reg, 13, 12, &Cores, Nb->ConfigHandle);

  return (UINT8) (Cores + 1);
}
示例#13
0
/**
 *  Returns the family specific properties of the cache, and its usage.
 *
 *  @CpuServiceMethod{::F_CPU_GET_FAMILY_SPECIFIC_ARRAY}.
 *
 *  @param[in]   FamilySpecificServices   The current Family Specific Services.
 *  @param[out]  CacheInfoPtr             Points to the cache info properties on exit.
 *  @param[out]  NumberOfElements         Will be one to indicate one entry.
 *  @param[in]   StdHeader                Header for library and services.
 *
 */
VOID
GetF15CacheInfo (
  IN       CPU_SPECIFIC_SERVICES *FamilySpecificServices,
     OUT   CONST VOID **CacheInfoPtr,
     OUT   UINT8 *NumberOfElements,
  IN       AMD_CONFIG_PARAMS *StdHeader
  )
{
  UINT32 Enabled;
  UINT32 DualCore;
  UINT32 Node;
  PCI_ADDR  PciAddress;
  CPU_SPECIFIC_SERVICES *FamilyServices;
  AP_MAILBOXES     ApMailboxes;
  CORE_PAIR_MAP *CorePairMap;
  AGESA_STATUS IgnoredStatus;

  if (!IsBsp (StdHeader, &IgnoredStatus)) {
    GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
    ASSERT (FamilyServices != NULL);

    FamilyServices->GetApMailboxFromHardware (FamilyServices, &ApMailboxes, StdHeader);
    Node = ApMailboxes.ApMailInfo.Fields.Node;

    // Since pre-heap, get compute unit status from hardware, using mailbox info.
    PciAddress.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0);
    PciAddress.Address.Device = PciAddress.Address.Device + Node;
    PciAddress.Address.Function = FUNC_5;
    PciAddress.Address.Register = COMPUTE_UNIT_STATUS;
    LibAmdPciReadBits (PciAddress, 3, 0, &Enabled, StdHeader);
    LibAmdPciReadBits (PciAddress, 19, 16, &DualCore, StdHeader);

    // Find the core to compute unit mapping for this node.
    CorePairMap = FamilyServices->CorePairMap;
    if ((Enabled != 0) && (CorePairMap != NULL)) {
      while (CorePairMap->Enabled != 0xFF) {
        if ((Enabled == CorePairMap->Enabled) && (DualCore == CorePairMap->DualCore)) {
          break;
        }
        CorePairMap++;
      }
      // The assert is for finding a processor configured in a way the core pair map doesn't support.
      ASSERT (CorePairMap->Enabled != 0xFF);
      switch (CorePairMap->Mapping) {
      case AllCoresMapping:
        // No cores are sharing a compute unit
        *CacheInfoPtr = &CpuF15CacheInfo;
        break;
      case EvenCoresMapping:
        // Cores are paired into compute units
        *CacheInfoPtr = &CpuF15CacheInfoCP;
        break;
      default:
        ASSERT (FALSE);
      }
    }
  } else {
    // the BSC is always just the first slice, we could return either one. Return the non for safest.
    *CacheInfoPtr = &CpuF15CacheInfo;
  }
  *NumberOfElements = 1;
}
示例#14
0
/**
 * 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);
    }
  }
}