예제 #1
0
파일: mpuNi3.c 프로젝트: AdriDlu/coreboot
/**
 *
 *     This is function gets the POR speed limit for U-DDR3 Ni
 *
 *     @param[in,out]   *NBPtr           Pointer to MEM_NB_BLOCK
 *
 *
 */
VOID
STATIC
MemPGetPORFreqLimitUNi3 (
  IN OUT   MEM_NB_BLOCK *NBPtr
  )
{
  UINT8 *DimmsPerChPtr;
  UINT8 MaxDimmPerCH;
  UINT16 SpeedLimit;

  DimmsPerChPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmPerCH = *DimmsPerChPtr;
  } else {
    MaxDimmPerCH = 2;
  }

  if (MaxDimmPerCH == 1) {
    if (NBPtr->RefPtr->DDR3Voltage == VOLT1_5) {
      //
      // Highest POR supported speed for Unbuffered dimm is 1333
      //
      SpeedLimit = DDR1333_FREQUENCY;
    } else {
      //
      // Max LV DDR3 Speed is 1066 for this silicon
      //
      SpeedLimit = DDR1066_FREQUENCY;
    }
  } else {
    //
    // Highest supported speed in 2DPC configuration is 1066
    //
    SpeedLimit = DDR1066_FREQUENCY;
    //
    // VOLT1_35 won't be supported while two DIMMs are populated in a channel
    //
    if ((NBPtr->RefPtr->DDR3Voltage == VOLT1_35) &&
       (NBPtr->ChannelPtr->Dimms == 2)) {
      NBPtr->RefPtr->DDR3Voltage = VOLT1_5;
      PutEventLog (AGESA_WARNING, MEM_WARNING_VOLTAGE_1_35_NOT_SUPPORTED, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
      SetMemError (AGESA_WARNING, NBPtr->MCTPtr);
    }
  }
  if (NBPtr->DCTPtr->Timings.TargetSpeed > SpeedLimit) {
    NBPtr->DCTPtr->Timings.TargetSpeed = SpeedLimit;
  } else if (NBPtr->DCTPtr->Timings.TargetSpeed == DDR667_FREQUENCY) {
    // Unbuffered DDR3 at 333MHz is not supported
    NBPtr->DCTPtr->Timings.DimmExclude |= NBPtr->DCTPtr->Timings.DctDimmValid;
    PutEventLog (AGESA_ERROR, MEM_ERROR_UNSUPPORTED_333MHZ_UDIMM, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
    SetMemError (AGESA_ERROR, NBPtr->MCTPtr);
    // Change target speed to highest value so it won't affect other channels when leveling frequency across the node.
    NBPtr->DCTPtr->Timings.TargetSpeed = UNSUPPORTED_DDR_FREQUENCY;
  }
}
예제 #2
0
파일: mprc32_3.c 프로젝트: AdriDlu/coreboot
/**
 *
 *     This is function gets the POR speed limit for R-DDR3 C32 DDR3
 *
 *     @param[in,out]   *NBPtr           Pointer to MEM_NB_BLOCK
 *
 *
 */
VOID
STATIC
MemPGetPORFreqLimitRC32_3 (
  IN OUT   MEM_NB_BLOCK *NBPtr
  )
{
  UINT8 *DimmsPerChPtr;
  UINT8 MaxDimmPerCH;
  UINT8 FreqLimitSize;
  UINT16 SpeedLimit;
  CONST POR_SPEED_LIMIT *FreqLimitPtr;
  DCT_STRUCT *DCTPtr;

  DCTPtr = NBPtr->DCTPtr;
  DimmsPerChPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmPerCH = *DimmsPerChPtr;
  } else {
    MaxDimmPerCH = 2;
  }

  if (MaxDimmPerCH == 4) {
    DCTPtr->Timings.DimmExclude |= DCTPtr->Timings.DctDimmValid;
    PutEventLog (AGESA_CRITICAL, MEM_ERROR_UNSUPPORTED_DIMM_CONFIG, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
    SetMemError (AGESA_CRITICAL, NBPtr->MCTPtr);
    // Change target speed to highest value so it won't affect other channels when leveling frequency across the node.
    NBPtr->DCTPtr->Timings.TargetSpeed = UNSUPPORTED_DDR_FREQUENCY;
    return;
  } else if (MaxDimmPerCH == 3) {
    FreqLimitPtr = C32RDdr3PSPorFreqLimit3D;
    FreqLimitSize = GET_SIZE_OF (C32RDdr3PSPorFreqLimit3D);
  } else if (MaxDimmPerCH == 2) {
    FreqLimitPtr = C32RDdr3PSPorFreqLimit2D;
    FreqLimitSize = GET_SIZE_OF (C32RDdr3PSPorFreqLimit2D);
  } else {
    FreqLimitPtr = C32RDdr3PSPorFreqLimit1D;
    FreqLimitSize = GET_SIZE_OF (C32RDdr3PSPorFreqLimit1D);
  }

  SpeedLimit = MemPGetPorFreqLimit (NBPtr, FreqLimitSize, FreqLimitPtr);

  if (SpeedLimit != 0) {
    if (DCTPtr->Timings.TargetSpeed > SpeedLimit) {
      DCTPtr->Timings.TargetSpeed = SpeedLimit;
    }
  } else {
    DCTPtr->Timings.DimmExclude |= DCTPtr->Timings.DctDimmValid;
    PutEventLog (AGESA_CRITICAL, MEM_ERROR_UNSUPPORTED_DIMM_CONFIG, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
    SetMemError (AGESA_CRITICAL, NBPtr->MCTPtr);
    // Change target speed to highest value so it won't affect other channels when leveling frequency across the node.
    NBPtr->DCTPtr->Timings.TargetSpeed = UNSUPPORTED_DDR_FREQUENCY;
  }
}
예제 #3
0
파일: mpsRb3.c 프로젝트: AdriDlu/coreboot
/**
 *
 *     This is function gets the POR speed limit for SO-DDR3 RB
 *
 *     @param[in,out]   *NBPtr           Pointer to MEM_NB_BLOCK
 *
 *
 */
VOID
STATIC
MemPGetPORFreqLimitSRb3 (
  IN OUT   MEM_NB_BLOCK *NBPtr
  )
{
  UINT8 *DimmsPerChPtr;
  UINT8 MaxDimmPerCH;
  UINT16 SpeedLimit;

  DimmsPerChPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmPerCH = *DimmsPerChPtr;
  } else {
    MaxDimmPerCH = 2;
  }

  if (MaxDimmPerCH == 1) {
    if (NBPtr->RefPtr->DDR3Voltage == VOLT1_5) {
      //
      // Highest POR supported speed for SODimm is 1333
      //
      SpeedLimit = DDR1333_FREQUENCY;
    } else {
      //
      // Max LV DDR3 Speed is 1066 for this silicon
      //
      SpeedLimit = DDR1066_FREQUENCY;
    }
  } else {
    //
    // Highest supported speed in 2DPC configuration is 1066
    //
    SpeedLimit = DDR1066_FREQUENCY;
    //
    // VOLT1_35 won't be supported while two DIMMs are populated in a channel
    //
    if ((NBPtr->RefPtr->DDR3Voltage == VOLT1_35) &&
       (NBPtr->ChannelPtr->Dimms == 2)) {
      NBPtr->RefPtr->DDR3Voltage = VOLT1_5;
      PutEventLog (AGESA_WARNING, MEM_WARNING_VOLTAGE_1_35_NOT_SUPPORTED, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
      SetMemError (AGESA_WARNING, NBPtr->MCTPtr);
    }
  }
  if (NBPtr->DCTPtr->Timings.TargetSpeed > SpeedLimit) {
    NBPtr->DCTPtr->Timings.TargetSpeed = SpeedLimit;
  }
}
예제 #4
0
파일: mprc32_3.c 프로젝트: AdriDlu/coreboot
BOOLEAN
STATIC
MemPDoPsRC32_3 (
  IN OUT   MEM_NB_BLOCK *NBPtr
  )
{
  CONST DRAM_TERM_ENTRY *DramTermPtr;
  UINT8 MaxDimmsPerChannel;
  UINT8 *DimmsPerChPtr;
  UINT8 DramTermSize;

  DramTermSize = 0;
  DramTermPtr = NULL;
  DimmsPerChPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmsPerChannel = *DimmsPerChPtr;
  } else {
    MaxDimmsPerChannel = 2;
  }

  if ((MaxDimmsPerChannel == 1) || (MaxDimmsPerChannel == 2)) {
    DramTermSize = GET_SIZE_OF (C32RDdr3DramTerm2D);
    DramTermPtr = C32RDdr3DramTerm2D;
  } else if (MaxDimmsPerChannel == 3) {
    DramTermSize = GET_SIZE_OF (C32RDdr3DramTerm3D);
    DramTermPtr = C32RDdr3DramTerm3D;
  } else {
    IDS_ERROR_TRAP;
  }

  if (!MemPGetDramTerm (NBPtr, DramTermSize, DramTermPtr)) {
    return FALSE;
  }
  //
  // Special Cases for certain configs not covered by the table
  //
  // SR-SR-SR 1.5v @1066 (Currently only 3DPCH config at 1066)
  if ((MaxDimmsPerChannel == 3) && (NBPtr->ChannelPtr->Dimms == 3) &&
      (NBPtr->DCTPtr->Timings.Speed == DDR1066_FREQUENCY)) {
    NBPtr->PsPtr->DramTerm = 5; //30 Ohms
  }

  return TRUE;
}
예제 #5
0
파일: mprhy3.c 프로젝트: Godkey/coreboot
BOOLEAN
STATIC
MemPDoPsRHy3 (
  IN OUT   MEM_NB_BLOCK *NBPtr
  )
{
  CONST DRAM_TERM_ENTRY *DramTermPtr;
  UINT8 MaxDimmsPerChannel;
  UINT8 *DimmsPerChPtr;
  UINT8 DramTermSize;

  DramTermSize = 0;
  DramTermPtr = NULL;
  DimmsPerChPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmsPerChannel = *DimmsPerChPtr;
  } else {
    MaxDimmsPerChannel = 2;
  }

  if ((MaxDimmsPerChannel == 1) || (MaxDimmsPerChannel == 2)) {
    DramTermSize = GET_SIZE_OF (HyRDdr3DramTerm2D);
    DramTermPtr = HyRDdr3DramTerm2D;
  } else if (MaxDimmsPerChannel == 3) {
    DramTermSize = GET_SIZE_OF (HyRDdr3DramTerm3D);
    DramTermPtr = HyRDdr3DramTerm3D;
  } else {
    IDS_ERROR_TRAP;
  }

  if (!MemPGetDramTerm (NBPtr, DramTermSize, DramTermPtr)) {
    return FALSE;
  }
  //
  // Special Cases for certain configs not covered by the table
  //
  // 3DPCH Fully populated.
  if ((MaxDimmsPerChannel == 3) && (NBPtr->ChannelPtr->Dimms == 3)) {
    NBPtr->PsPtr->DramTerm = 5; //30 Ohms
    NBPtr->PsPtr->QR_DramTerm = 1; // 60 Ohms
  }
  return TRUE;
}
예제 #6
0
파일: mpshy3.c 프로젝트: AdriDlu/coreboot
BOOLEAN
STATIC
MemPDoPsSHy3 (
  IN OUT   MEM_NB_BLOCK *NBPtr
  )
{
  CONST DRAM_TERM_ENTRY *DramTermPtr;
  UINT8 MaxDimmsPerChannel;
  UINT8 *DimmsPerChPtr;
  UINT8 DramTermSize;

  DramTermSize = 0;
  DramTermPtr = NULL;
  DimmsPerChPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmsPerChannel = *DimmsPerChPtr;
  } else {
    MaxDimmsPerChannel = 2;
  }

  if (MaxDimmsPerChannel == 1) {
    DramTermSize = GET_SIZE_OF (HySDdr3DramTerm1D);
    DramTermPtr = HySDdr3DramTerm1D;
  } else if (MaxDimmsPerChannel == 2) {
    DramTermSize = GET_SIZE_OF (HySDdr3DramTerm2D);
    DramTermPtr = HySDdr3DramTerm2D;
  } else {
    IDS_ERROR_TRAP;
  }

  if (!MemPGetDramTerm (NBPtr, DramTermSize, DramTermPtr)) {
    return FALSE;
  }

  return TRUE;
}
예제 #7
0
파일: mpsao.c 프로젝트: B-Rich/coreboot
/**
 *
 *    A sub-function which extracts Slow mode, Address timing and Output driver compensation value
 *    from a input table and store those value to a specific address.
 *
 *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
 *     @param[in]       *EntryOfTables     - Pointer to MEM_PSC_TABLE_BLOCK
 *
 *     @return          TRUE - Table values can be extracted per dimm population and ranks type.
 *     @return          FALSE - Table values cannot be extracted per dimm population and ranks type.
 *
 */
BOOLEAN
MemPGetSAO (
  IN OUT   MEM_NB_BLOCK *NBPtr,
  IN       MEM_PSC_TABLE_BLOCK *EntryOfTables
  )
{

  UINT8 i;
  UINT8 MaxDimmPerCh;
  UINT8 NOD;
  UINT8 TableSize;
  UINT32 CurDDRrate;
  UINT8 DDR3Voltage;
  UINT16 RankTypeOfPopulatedDimm;
  UINT16 RankTypeInTable;
  UINT8 PsoMaskSAO;
  DIMM_TYPE DimmType;
  CPU_LOGICAL_ID LogicalCpuid;
  UINT8 PackageType;
  PSCFG_SAO_ENTRY *TblPtr;
  CH_DEF_STRUCT *CurrentChannel;

  CurrentChannel = NBPtr->ChannelPtr;

  TblPtr = NULL;
  TableSize = 0;
  PackageType = 0;
  LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;
  MaxDimmPerCh = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
  NOD = (UINT8) 1 << (MaxDimmPerCh - 1);

  if (CurrentChannel->RegDimmPresent != 0) {
    DimmType = RDIMM_TYPE;
  } else if (CurrentChannel->SODimmPresent != 0) {
    DimmType = SODIMM_TYPE;
    if (FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_SOLDERED_DOWN_SODIMM_TYPE, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID, 0, NULL, NULL) != NULL) {
      DimmType = SODWN_SODIMM_TYPE;
    }
  } else if (CurrentChannel->LrDimmPresent != 0) {
    DimmType = LRDIMM_TYPE;
  } else {
    DimmType = UDIMM_TYPE;
  }

  i = 0;
  // Obtain table pointer, table size, Logical Cpuid and PSC type according to Dimm, NB and package type.
  while (EntryOfTables->TblEntryOfSAO[i] != NULL) {
    if (((EntryOfTables->TblEntryOfSAO[i])->Header.DimmType & DimmType) != 0) {
      if (((EntryOfTables->TblEntryOfSAO[i])->Header.NumOfDimm & NOD) != 0) {
        //
        // Determine if this is the expected NB Type
        //
        LogicalCpuid = (EntryOfTables->TblEntryOfSAO[i])->Header.LogicalCpuid;
        PackageType = (EntryOfTables->TblEntryOfSAO[i])->Header.PackageType;
        if (MemPIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
          TblPtr = (PSCFG_SAO_ENTRY *) ((EntryOfTables->TblEntryOfSAO[i])->TBLPtr);
          TableSize = (EntryOfTables->TblEntryOfSAO[i])->TableSize;
          break;
        }
      }
    }
    i++;
  }

  // Check whether no table entry is found.
  if (EntryOfTables->TblEntryOfSAO[i] == NULL) {
    IDS_HDT_CONSOLE (MEM_FLOW, "\nNo SlowAccMode, AddrTmg and ODCCtrl  table\n");
    return FALSE;
  }

  CurDDRrate = (UINT32) (1 << (CurrentChannel->DCTPtr->Timings.Speed / 66));
  DDR3Voltage = (UINT8) (1 << CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage));
  RankTypeOfPopulatedDimm = MemPGetPsRankType (CurrentChannel);

  for (i = 0; i < TableSize; i++) {
    MemPConstructRankTypeMap ((UINT16) TblPtr->Dimm0, (UINT16) TblPtr->Dimm1, (UINT16) TblPtr->Dimm2, &RankTypeInTable);
    if (TblPtr->DimmPerCh == MaxDimmPerCh) {
      if ((TblPtr->DDRrate & CurDDRrate) != 0) {
        if ((TblPtr->VDDIO & DDR3Voltage) != 0) {
          if ((RankTypeInTable & RankTypeOfPopulatedDimm) == RankTypeOfPopulatedDimm) {
            CurrentChannel->DctAddrTmg = TblPtr->AddTmgCtl;
            CurrentChannel->DctOdcCtl = TblPtr->ODC;
            CurrentChannel->SlowMode = (TblPtr->SlowMode == 1) ? TRUE : FALSE;
            break;
          }
        }
      }
    }
    TblPtr++;
  }

  //
  // If there is no entry, check if overriding values (SlowAccMode, AddrTmg and ODCCtrl) existed. If not, show no entry found.
  //
  PsoMaskSAO = (UINT8) MemPProceedTblDrvOverride (NBPtr, NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_TBLDRV_SLOWACCMODE);
  PsoMaskSAO &= (UINT8) MemPProceedTblDrvOverride (NBPtr, NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_TBLDRV_ODCCTRL);
  PsoMaskSAO &= (UINT8) MemPProceedTblDrvOverride (NBPtr, NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_TBLDRV_ADDRTMG);
  if ((PsoMaskSAO == 0) && (i == TableSize)) {
    IDS_HDT_CONSOLE (MEM_FLOW, "\nNo SlowAccMode, AddrTmg and ODCCtrl entries\n");
  } else {
    return TRUE;
  }

  if (NBPtr->SharedPtr->VoltageMap != VDDIO_DETERMINED) {
    return TRUE;
  }

  PutEventLog (AGESA_ERROR, MEM_ERROR_SAO_NOT_FOUND, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
  SetMemError (AGESA_ERROR, NBPtr->MCTPtr);
  if (!NBPtr->MemPtr->ErrorHandling (NBPtr->MCTPtr, NBPtr->Dct, EXCLUDE_ALL_CHIPSEL, &NBPtr->MemPtr->StdHeader)) {
    ASSERT (FALSE);
  }
  return FALSE;
}
예제 #8
0
파일: masda3.c 프로젝트: Godkey/coreboot
AGESA_STATUS
MemAGetPsCfgSDA3 (
  IN OUT   MEM_DATA_STRUCT *MemData,
  IN       UINT8 SocketID,
  IN OUT   CH_DEF_STRUCT *CurrentChannel
  )
{
  STATIC CONST PSCFG_ENTRY PSCfg[] = {
    {DDR800_FREQUENCY, 0xFF, 0x00000000, 0x00113222},
    {DDR1066_FREQUENCY, 0xFF, 0x00000000, 0x10113222},
    {DDR1333_FREQUENCY, 0xFF, 0x00000000, 0x20113222},
  };

  STATIC CONST ADV_R_PSCFG_WL_ODT_ENTRY PSCfgDIMMWlODT[] = {
    {SR_DIMM1,            {0x00, 0x02, 0x00, 0x00}, 1},
    {DR_DIMM1,            {0x00, 0x08, 0x00, 0x00}, 1},
    {SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1, {0x03, 0x03, 0x00, 0x00}, 2}
  };

  UINT16 i;
  UINT16 j;
  UINT8 Loads;
  UINT8 Dimms;
  UINT16 Speed;
  UINT32 AddrTmgCTL;
  UINT32 DctOdcCtl;
  UINT8 PhyWLODT[4];
  BOOLEAN SlowMode;
  UINT8  MaxDimmPerCH;
  UINT8 *DimmsPerChPtr;
  UINT16 DIMMRankType;
  UINT16 _DIMMRankType;
  UINT8 DimmTpMatch;

  ASSERT (MemData != 0);
  ASSERT (CurrentChannel != 0);

  AddrTmgCTL = 0;
  DctOdcCtl = 0;
  PhyWLODT[0] = 0x0F;
  PhyWLODT[1] = 0x0F;
  PhyWLODT[2] = 0x0F;
  PhyWLODT[3] = 0x0F;
  SlowMode = FALSE;  // 1T
  if ((CurrentChannel->MCTPtr->LogicalCpuid.Family & (AMD_FAMILY_10_DA | AMD_FAMILY_10_BL)) == 0) {
    return AGESA_UNSUPPORTED;
  }
  if (CurrentChannel->TechType != DDR3_TECHNOLOGY) {
    return AGESA_UNSUPPORTED;
  }
  if (CurrentChannel->SODimmPresent != CurrentChannel->ChDimmValid) {
    return AGESA_UNSUPPORTED;
  }
  // Prepare inputs
  Loads = CurrentChannel->Loads;
  Dimms = CurrentChannel->Dimms;
  Speed = CurrentChannel->DCTPtr->Timings.Speed;

  DIMMRankType = MemAGetPsRankType (CurrentChannel);

  DimmsPerChPtr = FindPSOverrideEntry (MemData->ParameterListPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, SocketID, CurrentChannel->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmPerCH = *DimmsPerChPtr;
  } else {
    MaxDimmPerCH = 2;
  }

  for (i = 0; i < GET_SIZE_OF (PSCfg); i++) {
    if (Speed == PSCfg[i].Speed) {
      if (Loads <= PSCfg[i].Loads) {
        AddrTmgCTL = PSCfg[i].AddrTmg;
        DctOdcCtl = PSCfg[i].Odc;
        break;
      }
    }
  }

  // WL ODT
  for (i = 0; i < GET_SIZE_OF (PSCfgDIMMWlODT); i++) {
    if (Dimms != PSCfgDIMMWlODT[i].Dimms) {
      continue;
    }
    DimmTpMatch = 0;
    _DIMMRankType = DIMMRankType & PSCfgDIMMWlODT[i].DIMMRankType;
    for (j = 0; j < MAX_DIMMS_PER_CHANNEL; j++) {
      if ((_DIMMRankType & (UINT16) 0x0F << (j << 2)) != 0) {
        DimmTpMatch++;
      }
    }
    if (DimmTpMatch == PSCfgDIMMWlODT[i].Dimms) {
      PhyWLODT[0] = PSCfgDIMMWlODT[i].PhyWrLvOdt[0];
      PhyWLODT[1] = PSCfgDIMMWlODT[i].PhyWrLvOdt[1];
      PhyWLODT[2] = PSCfgDIMMWlODT[i].PhyWrLvOdt[2];
      PhyWLODT[3] = PSCfgDIMMWlODT[i].PhyWrLvOdt[3];
      break;
    }
  }

  //
  // Overrides and/or exceptions
  //
  if (MaxDimmPerCH == 2) {
    if (Dimms == 2) {
      DctOdcCtl = 0x20223323;
      SlowMode = TRUE;
      if (Speed == DDR800_FREQUENCY) {
        AddrTmgCTL = 0x00000039;
      } else if (Speed == DDR1066_FREQUENCY) {
        AddrTmgCTL = 0x00000037;
      }
    } else {
      DctOdcCtl = 0x20113222;
    }
  } else {
    if (CurrentChannel->DimmSRPresent != 0) {
      PhyWLODT[0] = 1;
    } else if (CurrentChannel->DimmDrPresent != 0) {
      PhyWLODT[0] = 4;
    }
  }

  CurrentChannel->MemClkDisMap = (UINT8 *) DASDdr3CLKDis;
  CurrentChannel->CKETriMap = (UINT8 *) DASDdr3CKETri;
  CurrentChannel->ODTTriMap = (UINT8 *) DASDdr3ODTTri;
  CurrentChannel->ChipSelTriMap = (UINT8 *) DASDdr3CSTri;

  CurrentChannel->DctAddrTmg = AddrTmgCTL;
  CurrentChannel->DctOdcCtl = DctOdcCtl;
  for (i = 0; i < sizeof (CurrentChannel->PhyWLODT); i++) {
    CurrentChannel->PhyWLODT[i] = PhyWLODT[i];
  }
  CurrentChannel->SlowMode = SlowMode;

  return AGESA_SUCCESS;
}
예제 #9
0
파일: mauhy3.c 프로젝트: Godkey/coreboot
AGESA_STATUS
MemAGetPsCfgUHy3 (
  IN OUT   MEM_DATA_STRUCT *MemData,
  IN       UINT8 SocketID,
  IN OUT   CH_DEF_STRUCT *CurrentChannel
  )
{
  STATIC CONST PSCFG_ENTRY PSCfg[] = {
    {DDR800_FREQUENCY, 0xFF, 0x00390039, 0x20223323},
    {DDR1066_FREQUENCY, 0xFF, 0x00350037, 0x20223323},
    {DDR1333_FREQUENCY, 0xFF, 0x00000035, 0x20223323},
    {DDR1600_FREQUENCY, 0xFF, 0x00000033, 0x20223323}
  };

  STATIC CONST ADV_PSCFG_ODT_ENTRY PSCfg2DIMMsODT[] = {
    {SR_DIMM0, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 1},
    {DR_DIMM0, 0x00000000, 0x00000000, 0x00000104, 0x00000000, 1},
    {SR_DIMM1, 0x00000000,0x00000000,0x00020000, 0x00000000, 1},
    {DR_DIMM1, 0x00000000,0x00000000,0x02080000, 0x00000000, 1},
    {SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1, 0x01010202,0x00000000,0x09030603, 0x00000000, 2},
  };

  STATIC CONST ADV_R_PSCFG_WL_ODT_ENTRY PSCfg2DIMMsWlODT[] = {
    {SR_DIMM0,            {0x01, 0x00, 0x00, 0x00}, 1},
    {DR_DIMM0,            {0x04, 0x00, 0x00, 0x00}, 1},
    {SR_DIMM1,            {0x00, 0x02, 0x00, 0x00}, 1},
    {DR_DIMM1,            {0x00, 0x08, 0x00, 0x00}, 1},
    {SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1, {0x03, 0x03, 0x00, 0x00}, 2}
  };

  STATIC CONST ADV_PSCFG_ODT_ENTRY PSCfg3DIMMsODT[] = {
    {SR_DIMM2 + DR_DIMM2, 0x00000000, 0x00000000, 0x00000000, 0x00000404, 1},
    //{SR_DIMM0 + DR_DIMM0, 0x00000000, 0x00000000, 0x00000101, 0x00000000, 1},
    {SR_DIMM0 + DR_DIMM0 + SR_DIMM2 + DR_DIMM2, 0x00000404, 0x00000101, 0x00000405, 0x00000105, 2},
    //{SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1 + SR_DIMM2 + DR_DIMM2, 0x05050606, 0x00000303, 0x0D070607, 0x00000307, 3},
  };

  STATIC CONST ADV_R_PSCFG_WL_ODT_ENTRY PSCfg3DIMMsWlODT[] = {
    {SR_DIMM2 + DR_DIMM2, {0x00, 0x00, 0x04, 0x00}, 1},
    //{SR_DIMM0 + DR_DIMM0, {0x01, 0x02, 0x00, 0x00}, 1},
    {SR_DIMM0 + DR_DIMM0 + SR_DIMM2 + DR_DIMM2, {0x05, 0x00, 0x05, 0x00}, 2},
    //{SR_DIMM0 + DR_DIMM0 + SR_DIMM1 + DR_DIMM1 + SR_DIMM2 + DR_DIMM2, {0x07, 0x07, 0x07, 0x00}, 3},
  };

  UINT16 i;
  UINT16 j;
  UINT8  MaxDimmPerCH;
  UINT8 Loads;
  UINT8 Dimms;
  UINT16 Speed;
  UINT16 DIMMRankType;
  UINT16 _DIMMRankType;
  UINT32 AddrTmgCTL;
  UINT32 DctOdcCtl;
  UINT32 PhyRODTCSLow;
  UINT32 PhyRODTCSHigh;
  UINT32 PhyWODTCSLow;
  UINT32 PhyWODTCSHigh;
  UINT8 PhyWLODT[4];
  UINT8 PSCfgODTSize;
  UINT8 PSCfgWlODTSize;
  BOOLEAN SlowMode;
  UINT8 DimmTpMatch;
  CONST ADV_PSCFG_ODT_ENTRY *PSCfgODTPtr;
  CONST ADV_R_PSCFG_WL_ODT_ENTRY *PSCfgWlODTPtr;
  UINT8 *DimmsPerChPtr;

  ASSERT (MemData != NULL);
  ASSERT (CurrentChannel != NULL);

  AddrTmgCTL = 0;
  DctOdcCtl = 0;
  PhyRODTCSLow = 0;
  PhyRODTCSHigh = 0;
  PhyWODTCSLow = 0;
  PhyWODTCSHigh = 0;
  PhyWLODT[0] = 0x0F;
  PhyWLODT[1] = 0x0F;
  PhyWLODT[2] = 0x0F;
  PhyWLODT[3] = 0x0F;

  if ((CurrentChannel->MCTPtr->LogicalCpuid.Family & AMD_FAMILY_10_HY) == 0) {
    return AGESA_UNSUPPORTED;
  }
  if (CurrentChannel->TechType != DDR3_TECHNOLOGY) {
    return AGESA_UNSUPPORTED;
  }
  if (CurrentChannel->RegDimmPresent) {
    return AGESA_UNSUPPORTED;
  }
  // Prepare inputs

  DimmsPerChPtr = FindPSOverrideEntry (MemData->ParameterListPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, SocketID, CurrentChannel->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmPerCH = *DimmsPerChPtr;
  } else {
    MaxDimmPerCH = 2;
  }

  Loads = CurrentChannel->Loads;
  Dimms = CurrentChannel->Dimms;
  Speed = CurrentChannel->DCTPtr->Timings.Speed;

  DIMMRankType = MemAGetPsRankType (CurrentChannel);

  if ((Speed == DDR1333_FREQUENCY || Speed == DDR1600_FREQUENCY) && (Dimms == 2)) {
    SlowMode = TRUE;   // 2T
  } else {
    SlowMode = FALSE;  // 1T
  }

  for (i = 0; i < GET_SIZE_OF (PSCfg); i++) {
    if (Speed == PSCfg[i].Speed) {
      if (Loads <= PSCfg[i].Loads) {
        AddrTmgCTL = PSCfg[i].AddrTmg;
        DctOdcCtl = PSCfg[i].Odc;
        break;
      }
    }
  }

  ASSERT (i < GET_SIZE_OF (PSCfg));

  if (MaxDimmPerCH == 3) {
    PSCfgODTPtr = PSCfg3DIMMsODT;
    PSCfgWlODTPtr = PSCfg3DIMMsWlODT;
    PSCfgODTSize = sizeof (PSCfg3DIMMsODT) / sizeof (ADV_PSCFG_ODT_ENTRY);
    PSCfgWlODTSize = sizeof (PSCfg3DIMMsWlODT) / sizeof (ADV_R_PSCFG_WL_ODT_ENTRY);
  } else {
    PSCfgODTPtr = PSCfg2DIMMsODT;
    PSCfgWlODTPtr = PSCfg2DIMMsWlODT;
    PSCfgODTSize = sizeof (PSCfg2DIMMsODT) / sizeof (ADV_PSCFG_ODT_ENTRY);
    PSCfgWlODTSize = sizeof (PSCfg2DIMMsWlODT) / sizeof (ADV_R_PSCFG_WL_ODT_ENTRY);
  }

  // Programmable ODT
  for (i = 0; i  < PSCfgODTSize; i++, PSCfgODTPtr++) {
    if (Dimms != PSCfgODTPtr->Dimms) {
      continue;
    }
    DimmTpMatch = 0;
    _DIMMRankType = DIMMRankType & PSCfgODTPtr->DIMMRankType;
    for (j = 0; j < MAX_DIMMS_PER_CHANNEL; j++) {
      if ((_DIMMRankType & (UINT16) 0x0F << (j << 2)) != 0) {
        DimmTpMatch++;
      }
    }
    if (DimmTpMatch == PSCfgODTPtr->Dimms) {
      PhyRODTCSLow = PSCfgODTPtr->PhyRODTCSLow;
      PhyRODTCSHigh = PSCfgODTPtr->PhyRODTCSHigh;
      PhyWODTCSLow = PSCfgODTPtr->PhyWODTCSLow;
      PhyWODTCSHigh = PSCfgODTPtr->PhyWODTCSHigh;
      break;
    }
  }

  // WL ODT
  for (i = 0; i  < PSCfgWlODTSize; i++, PSCfgWlODTPtr++) {
    if (Dimms != PSCfgWlODTPtr->Dimms) {
      continue;
    }
    DimmTpMatch = 0;
    _DIMMRankType = DIMMRankType & PSCfgWlODTPtr->DIMMRankType;
    for (j = 0; j < MAX_DIMMS_PER_CHANNEL; j++) {
      if ((_DIMMRankType & (UINT16) 0x0F << (j << 2)) != 0) {
        DimmTpMatch++;
      }
    }
    if (DimmTpMatch == PSCfgWlODTPtr->Dimms) {
      PhyWLODT[0] = PSCfgWlODTPtr->PhyWrLvOdt[0];
      PhyWLODT[1] = PSCfgWlODTPtr->PhyWrLvOdt[1];
      PhyWLODT[2] = PSCfgWlODTPtr->PhyWrLvOdt[2];
      PhyWLODT[3] = PSCfgWlODTPtr->PhyWrLvOdt[3];
      break;
    }
  }

  //
  // Overrides and/or exceptions
  //
  if (Dimms == 1) {
    if (Loads >= 16) {
      if (Speed == DDR800_FREQUENCY) {
        AddrTmgCTL = 0x003B0000;
      } else if (Speed == DDR1066_FREQUENCY) {
        AddrTmgCTL = 0x00380000;
      } else if (Speed == DDR1333_FREQUENCY) {
        AddrTmgCTL = 0x00360000;
      } else {
        AddrTmgCTL = 0x00340000;
        SlowMode = TRUE;
      }
    } else {
      AddrTmgCTL = 0;
    }
    DctOdcCtl = 0x20113222;
  }

  CurrentChannel->MemClkDisMap = (UINT8 *) HyUDdr3CLKDis;
  CurrentChannel->CKETriMap = (UINT8 *) HyUDdr3CKETri;
  CurrentChannel->ChipSelTriMap = (UINT8 *) HyUDdr3CSTri;

  switch (MaxDimmPerCH) {
  case 3:
    CurrentChannel->ODTTriMap = (UINT8 *) HyUDdr3ODTTri3D;
    break;
  default:
    CurrentChannel->ODTTriMap = (UINT8 *) HyUDdr3ODTTri2D;  // Most conservative
  }

  CurrentChannel->DctEccDqsLike = 0x0403;
  CurrentChannel->DctEccDqsScale = 0x70;
  CurrentChannel->DctAddrTmg = AddrTmgCTL;
  CurrentChannel->DctOdcCtl = DctOdcCtl;
  CurrentChannel->PhyRODTCSLow  = PhyRODTCSLow;
  CurrentChannel->PhyRODTCSHigh = PhyRODTCSHigh;
  CurrentChannel->PhyWODTCSLow  = PhyWODTCSLow;
  CurrentChannel->PhyWODTCSHigh = PhyWODTCSHigh;
  for (i = 0; i < sizeof (CurrentChannel->PhyWLODT); i++) {
    CurrentChannel->PhyWLODT[i] = PhyWLODT[i];
  }
  CurrentChannel->SlowMode = SlowMode;

  return AGESA_SUCCESS;
}
예제 #10
0
파일: mpseeds.c 프로젝트: B-Rich/coreboot
/**
 *
 *    A sub-function extracts WL and HW RxEn seeds from PSCFG tables
 *    from a input table
 *
 *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
 *     @param[in]       *EntryOfTables     - Pointer to MEM_PSC_TABLE_BLOCK
 *
 *     @return          NBPtr->PsPtr->WLSeedVal
 *     @return          NBPtr->PsPtr->HWRxENSeedVal
 *
 */
BOOLEAN
MemPGetTrainingSeeds (
  IN OUT   MEM_NB_BLOCK *NBPtr,
  IN       MEM_PSC_TABLE_BLOCK *EntryOfTables
  )
{

  UINT8 i;
  UINT8 MaxDimmPerCh;
  UINT8 NOD;
  UINT8 TableSize;
  DIMM_TYPE DimmType;
  CPU_LOGICAL_ID LogicalCpuid;
  UINT8 PackageType;
  UINT8 Seedloop;
  UINT8 CH;
  PSC_TBL_ENTRY **TblEntryPtr;
  PSCFG_SEED_ENTRY *TblPtr;
  CH_DEF_STRUCT *CurrentChannel;

  CurrentChannel = NBPtr->ChannelPtr;
  TblEntryPtr = NULL;
  TblPtr = NULL;
  TableSize = 0;
  PackageType = 0;
  LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;
  MaxDimmPerCh = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
  NOD = (UINT8) 1 << (MaxDimmPerCh - 1);
  CH = 1 << (CurrentChannel->ChannelID);

  if (CurrentChannel->RegDimmPresent != 0) {
    DimmType = RDIMM_TYPE;
  } else if (CurrentChannel->SODimmPresent != 0) {
    DimmType = SODIMM_TYPE;
    if (FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_SOLDERED_DOWN_SODIMM_TYPE, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID, 0, NULL, NULL) != NULL) {
      DimmType = SODWN_SODIMM_TYPE;
    }
  } else if (CurrentChannel->LrDimmPresent != 0) {
    DimmType = LRDIMM_TYPE;
  } else {
    DimmType = UDIMM_TYPE;
  }

  // Get seed value of WL, then HW RxEn
  for (Seedloop = 0; Seedloop < 2; Seedloop++) {
    TblEntryPtr = (Seedloop == 0) ? EntryOfTables->TblEntryOfWLSeed : EntryOfTables->TblEntryOfHWRxENSeed;

    i = 0;
    // Obtain table pointer, table size, Logical Cpuid and PSC type according to Dimm, NB and package type.
    while (TblEntryPtr[i] != NULL) {
      if (((TblEntryPtr[i])->Header.DimmType & DimmType) != 0) {
        //
        // Determine if this is the expected NB Type
        //
        LogicalCpuid = (TblEntryPtr[i])->Header.LogicalCpuid;
        PackageType = (TblEntryPtr[i])->Header.PackageType;
        if (MemPIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
          TblPtr = (PSCFG_SEED_ENTRY *) ((TblEntryPtr[i])->TBLPtr);
          TableSize = (TblEntryPtr[i])->TableSize;
          break;
        }
      }
      i++;
    }

    // Check whether no table entry is found.
    if (TblEntryPtr[i] == NULL) {
      IDS_HDT_CONSOLE (MEM_FLOW, "\nNo %s training seeds Config table\n", (Seedloop == 0) ? "WL" : "HW RxEn");
      return FALSE;
    }

    for (i = 0; i < TableSize; i++) {
      if ((TblPtr->DimmPerCh & NOD) != 0) {
        if ((TblPtr->Channel & CH) != 0) {
          if (Seedloop == 0) {
            NBPtr->PsPtr->WLSeedVal = (UINT8) TblPtr->SeedVal;
          } else {
            NBPtr->PsPtr->HWRxENSeedVal = TblPtr->SeedVal;
          }
          break;
        }
      }
      TblPtr++;
    }

    if (i == TableSize) {
      IDS_HDT_CONSOLE (MEM_FLOW, "\nNo %s seed entries\n\n", (Seedloop == 0) ? "WL" : "HW RxEn");
      PutEventLog (AGESA_ERROR, MEM_ERROR_TRAINING_SEED_NOT_FOUND, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
      SetMemError (AGESA_ERROR, NBPtr->MCTPtr);
      if (!NBPtr->MemPtr->ErrorHandling (NBPtr->MCTPtr, NBPtr->Dct, EXCLUDE_ALL_CHIPSEL, &NBPtr->MemPtr->StdHeader)) {
        ASSERT (FALSE);
      }
      return FALSE;
    }
  }

  return TRUE;
}
예제 #11
0
파일: mnphy.c 프로젝트: fishbaoz/KaveriPI
VOID
MemNPhyFenceTrainingUnb (
  IN OUT   MEM_NB_BLOCK *NBPtr
  )
{
  UINT8 FenceThresholdTxDll;
  UINT8 FenceThresholdRxDll;
  UINT8 FenceThresholdTxPad;
  UINT16 Fence2Data;

  MemNSetBitFieldNb (NBPtr, BFDataFence2, 0);
  MemNSetBitFieldNb (NBPtr, BFFence2, 0);
  // 1. Program D18F2x[1,0]9C_x0000_0008[FenceTrSel]=10b.
  // 2. Perform phy fence training.
  // 3. Write the calculated fence value to D18F2x[1,0]9C_x0000_000C[FenceThresholdTxDll].
  MemNSetBitFieldNb (NBPtr, BFFenceTrSel, 2);
  MAKE_TSEFO (NBPtr->NBRegTable, DCT_PHY_ACCESS, 0x0C, 30, 26, BFPhyFence);
  IDS_HDT_CONSOLE (MEM_FLOW, "\t\tFenceThresholdTxDll\n");
  MemNTrainPhyFenceNb (NBPtr);
  FenceThresholdTxDll = (UINT8) MemNGetBitFieldNb (NBPtr, BFPhyFence);
  NBPtr->FamilySpecificHook[DetectMemPllError] (NBPtr, &FenceThresholdTxDll);

  // 4. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]0F[AlwaysEnDllClks]=001b.
  MemNSetBitFieldNb (NBPtr, BFAlwaysEnDllClks, 0x1000);

  // 5. Program D18F2x[1,0]9C_x0000_0008[FenceTrSel]=01b.
  // 6. Perform phy fence training.
  // 7. Write the calculated fence value to D18F2x[1,0]9C_x0000_000C[FenceThresholdRxDll].
  MemNSetBitFieldNb (NBPtr, BFFenceTrSel, 1);
  MAKE_TSEFO (NBPtr->NBRegTable, DCT_PHY_ACCESS, 0x0C, 25, 21, BFPhyFence);
  IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tFenceThresholdRxDll\n");
  MemNTrainPhyFenceNb (NBPtr);
  FenceThresholdRxDll = (UINT8) MemNGetBitFieldNb (NBPtr, BFPhyFence);
  NBPtr->FamilySpecificHook[DetectMemPllError] (NBPtr, &FenceThresholdRxDll);

  // 8. Program D18F2x[1,0]9C_x0D0F_0[F,7:0]0F[AlwaysEnDllClks]=000b.
  MemNSetBitFieldNb (NBPtr, BFAlwaysEnDllClks, 0x0000);

  // 9. Program D18F2x[1,0]9C_x0000_0008[FenceTrSel]=11b.
  // 10. Perform phy fence training.
  // 11. Write the calculated fence value to D18F2x[1,0]9C_x0000_000C[FenceThresholdTxPad].
  MemNSetBitFieldNb (NBPtr, BFFenceTrSel, 3);
  MAKE_TSEFO (NBPtr->NBRegTable, DCT_PHY_ACCESS, 0x0C, 20, 16, BFPhyFence);
  IDS_HDT_CONSOLE (MEM_FLOW, "\n\t\tFenceThresholdTxPad\n");
  MemNTrainPhyFenceNb (NBPtr);
  FenceThresholdTxPad = (UINT8) MemNGetBitFieldNb (NBPtr, BFPhyFence);
  NBPtr->FamilySpecificHook[DetectMemPllError] (NBPtr, &FenceThresholdTxPad);

  // Program Fence2 threshold for Clk, Cmd, and Addr
  if (FenceThresholdTxPad < 16) {
    MemNSetBitFieldNb (NBPtr, BFClkFence2, FenceThresholdTxPad | 0x10);
    MemNSetBitFieldNb (NBPtr, BFCmdFence2, FenceThresholdTxPad | 0x10);
    MemNSetBitFieldNb (NBPtr, BFAddrFence2, FenceThresholdTxPad | 0x10);
  } else {
    MemNSetBitFieldNb (NBPtr, BFClkFence2, 0);
    MemNSetBitFieldNb (NBPtr, BFCmdFence2, 0);
    MemNSetBitFieldNb (NBPtr, BFAddrFence2, 0);
  }

  // Program Fence2 threshold for data
  Fence2Data = 0;
  if (FenceThresholdTxPad < 16) {
    Fence2Data |= FenceThresholdTxPad | 0x10;
  }
  if (FenceThresholdRxDll < 16) {
    Fence2Data |= (FenceThresholdRxDll | 0x10) << 10;
  }
  if (FenceThresholdTxDll < 16) {
    Fence2Data |= (FenceThresholdTxDll | 0x10) << 5;
  }
  MemNSetBitFieldNb (NBPtr, BFDataFence2, Fence2Data);
  NBPtr->FamilySpecificHook[ProgramFence2RxDll] (NBPtr, &Fence2Data);

  if (NBPtr->MCTPtr->Status[SbLrdimms]) {
    // 18. If motherboard routing requires CS[7:6] to adopt address timings, e.g. 3 LRDIMMs/ch with CS[7:6]
    // routed across all DIMM sockets, BIOS performs the following:
    if (FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_NO_LRDIMM_CS67_ROUTING, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID, 0, NULL, NULL) != NULL) {
      //   A. Program D18F2xA8_dct[1:0][CSTimingMux67] = 1.
      MemNSetBitFieldNb (NBPtr, BFCSTimingMux67, 1);
      //   B. Program D18F2x9C_x0D0F_8021_dct[1:0]:
      //       - DiffTimingEn = 1.
      //       - IF (D18F2x9C_x0000_0004_dct[1:0][AddrCmdFineDelay] >=
      //         D18F2x9C_x0D0F_E008_dct[1:0][FenceValue]) THEN Fence = 1 ELSE Fence = 0.
      //       - Delay = D18F2x9C_x0000_0004_dct[1:0][AddrCmdFineDelay].
      //
      MemNSetBitFieldNb (NBPtr, BFDiffTimingEn, 1);
      MemNSetBitFieldNb (NBPtr, BFFence, (MemNGetBitFieldNb (NBPtr, BFAddrCmdFineDelay) >= MemNGetBitFieldNb (NBPtr, BFFenceValue)) ? 1 : 0);
      MemNSetBitFieldNb (NBPtr, BFDelay, (MemNGetBitFieldNb (NBPtr, BFAddrCmdFineDelay)));
    }
  }

  // 19. Reprogram F2x9C_04.
  MemNSetBitFieldNb (NBPtr, BFAddrTmgControl, MemNGetBitFieldNb (NBPtr, BFAddrTmgControl));

}
예제 #12
0
파일: mnphyhy.c 프로젝트: AdriDlu/coreboot
VOID
MemNInitPhyCompHy (
  IN OUT   MEM_NB_BLOCK *NBPtr
  )
{
  CONST UINT8 TableCompRiseSlew20x[] = {7, 3, 2, 2};
  CONST UINT8 TableCompRiseSlew15x[] = {7, 7, 3, 2};
  CONST UINT8 TableCompFallSlew20x[] = {7, 5, 3, 2};
  CONST UINT8 TableCompFallSlew15x[] = {7, 7, 5, 3};
  UINT8 i;
  UINT8 j;
  UINT8 CurrDct;
  UINT8 MaxDimmsPerChannel;
  UINT8 *DimmsPerChPtr;

  CurrDct = NBPtr->Dct;

  //
  // Get Platform Information
  //
  DimmsPerChPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmsPerChannel = *DimmsPerChPtr;
  } else {
    MaxDimmsPerChannel = 2;
  }

  // 1. BIOS disables the phy compensation register by programming F2x9C_x08[DisAutoComp]=1
  // 2. BIOS waits 5 us for the disabling of the compensation engine to complete.
  // DisAutoComp will be cleared after Dram init has completed
  //
  MemNSwitchDCTNb (NBPtr, 0);
  MemNSetBitFieldNb (NBPtr, BFDisAutoComp, 1);
  MemUWait10ns (500, NBPtr->MemPtr);
  MemNSwitchDCTNb (NBPtr, CurrDct);

  // 3. For each normalized driver strength code read from
  // F2x[1, 0]9C_x00[AddrCmdDrvStren], program the
  // corresponding 3 bit predriver code in F2x9C_x0A[D3Cmp1NCal, D3Cmp1PCal].
  //
  // 4. For each normalized driver strength code read from
  // F2x[1, 0]9C_x00[DataDrvStren], program the corresponding
  // 3 bit predriver code in F2x9C_x0A[D3Cmp0NCal, D3Cmp0PCal, D3Cmp2NCal,
  // D3Cmp2PCal].
  //
  j = (UINT8) MemNGetBitFieldNb (NBPtr, BFAddrCmdDrvStren);
  i = (UINT8) MemNGetBitFieldNb (NBPtr, BFDataDrvStren);

  MemNSwitchDCTNb (NBPtr, 0);
  ASSERT (j <= 3);
  MemNSetBitFieldNb (NBPtr, BFD3Cmp1NCal, TableCompRiseSlew20x[j]);
  MemNSetBitFieldNb (NBPtr, BFD3Cmp1PCal, TableCompFallSlew20x[j]);

  ASSERT (i <= 3);
  MemNSetBitFieldNb (NBPtr, BFD3Cmp0NCal, TableCompRiseSlew15x[i]);
  MemNSetBitFieldNb (NBPtr, BFD3Cmp0PCal, TableCompFallSlew15x[i]);
  MemNSetBitFieldNb (NBPtr, BFD3Cmp2NCal, TableCompRiseSlew15x[i]);
  MemNSetBitFieldNb (NBPtr, BFD3Cmp2PCal, TableCompFallSlew15x[i]);

  //
  // Special Case for certain configs
  //
  // 3DPCH Fully populated.
  if ((MaxDimmsPerChannel == 3) && (NBPtr->ChannelPtr->Dimms == 3)) {
    MemNSetBitFieldNb (NBPtr, BFD3Cmp0NCal, 3);
    MemNSetBitFieldNb (NBPtr, BFD3Cmp0PCal, 5);
    MemNSetBitFieldNb (NBPtr, BFD3Cmp2NCal, 3);
    MemNSetBitFieldNb (NBPtr, BFD3Cmp2PCal, 5);
  }

  MemNSwitchDCTNb (NBPtr, CurrDct);
}
예제 #13
0
파일: mardr2.c 프로젝트: Godkey/coreboot
AGESA_STATUS
MemAGetPsCfgRDr2 (
  IN OUT   MEM_DATA_STRUCT *MemData,
  IN       UINT8 SocketID,
  IN OUT   CH_DEF_STRUCT *CurrentChannel
  )
{
  STATIC CONST ADV_PSCFG_ENTRY PSCfg4D[] = {
    {ANY_, ANY_, 0x00000000, 0x00111222, 1},
    {ANY_, ANY_, 0x00370000, 0x00111222, 2}
  };

  STATIC CONST ADV_PSCFG_ENTRY PSCfg8D[] = {
    {ANY_, ANY_, 0x00000000, 0x00111222, 1},
    {ANY_, ANY_, 0x00370000, 0x00111222, 2},
    {ANY_, ANY_, 0x002F0000, 0x00111222, ANY_}
  };

  CONST ADV_PSCFG_ENTRY *PSCfgPtr;
  UINT16 i;
  UINT8  MaxDimmPerCH;
  UINT16 TabSize;
  UINT8 Loads;
  UINT8 Dimms;
  UINT16 Speed;
  UINT32 AddrTmgCTL;
  UINT32 DctOdcCtl;
  UINT16 QRPresent;
  UINT16 DRx4Present;
  BOOLEAN SlowMode;
  UINT8 *DimmsPerChPtr;

  ASSERT (MemData != 0);
  ASSERT (CurrentChannel != 0);

  if ((CurrentChannel->MCTPtr->LogicalCpuid.Family & AMD_FAMILY_10_RB) == 0) {
    return AGESA_UNSUPPORTED;
  }
  if (CurrentChannel->TechType != DDR2_TECHNOLOGY) {
    return AGESA_UNSUPPORTED;
  }
  if (CurrentChannel->RegDimmPresent != CurrentChannel->ChDimmValid) {
    return AGESA_UNSUPPORTED;
  }

  // Prepare inputs
  Loads = CurrentChannel->Loads;
  Dimms = CurrentChannel->Dimms;
  Speed = CurrentChannel->DCTPtr->Timings.Speed;
  DimmsPerChPtr = FindPSOverrideEntry (MemData->ParameterListPtr->PlatformMemoryConfiguration, PSO_MAX_DIMMS, SocketID, CurrentChannel->ChannelID);
  if (DimmsPerChPtr != NULL) {
    MaxDimmPerCH = *DimmsPerChPtr;
  } else {
    MaxDimmPerCH = 2;
  }
  QRPresent = CurrentChannel->DimmQrPresent;
  DRx4Present = CurrentChannel->DimmDrPresent & CurrentChannel->Dimmx4Present;
  if (QRPresent) {
    Dimms = (Dimms + 1) / 2;
  }

  // Table look up
  if (MaxDimmPerCH <= 2) {
    PSCfgPtr = PSCfg4D;
    TabSize = GET_SIZE_OF (PSCfg4D);
  } else {
    PSCfgPtr = PSCfg8D;
    TabSize = GET_SIZE_OF (PSCfg8D);
  }
  DctOdcCtl = 0;
  AddrTmgCTL = 0;
  for (i = 0; i < TabSize; i++) {
    if ((PSCfgPtr[i].Dimms == ANY_) || (PSCfgPtr[i].Dimms == Dimms)) {
      if ((PSCfgPtr[i].Speed == ANY_) || (PSCfgPtr[i].Speed == Speed)) {
        if ((PSCfgPtr[i].Loads == ANY_) || (PSCfgPtr[i].Loads >= Loads)) {
          AddrTmgCTL = PSCfgPtr[i].AddrTmg;
          DctOdcCtl = PSCfgPtr[i].Odc;
          break;
        }
      }
    }
  }
  ASSERT (i == TabSize);
  SlowMode = FALSE;  // 1T

  //
  // Overrides and/or exceptions
  //

  if (QRPresent == 0x55) {
    // QR for 4DIMM case only
    AddrTmgCTL = 0x002F0000;
    if (Speed >= DDR667_FREQUENCY) {
      DctOdcCtl = 0x00331222;
    }
  }

  if (Speed >= DDR667_FREQUENCY) {
    if ((QRPresent != 0) || (DRx4Present != 0)) {
      AddrTmgCTL |= 0x00002F00;
    }
    if (Dimms >= 3) {
      AddrTmgCTL |= 0x0000002F;
    }
    if (Dimms == 3 || Dimms == 4) {
      DctOdcCtl = 0x00331222;
    }
  }

  // Adjust Processor ODT
  if (Dimms == 1) {
    DctOdcCtl |= 0x20000000;        // 75ohms
  } else {
    DctOdcCtl |= 0x10000000;        // 150ohms
  }

  CurrentChannel->MemClkDisMap = (UINT8 *) DrRDdr2CLKDis;
  CurrentChannel->CKETriMap = (UINT8 *) DrRDdr2CKETri;
  CurrentChannel->ChipSelTriMap = (UINT8 *) DrRDdr2CSTri;

  switch (MaxDimmPerCH) {
  case 3:
    CurrentChannel->ODTTriMap = (UINT8 *) DrRDdr2ODTTri3D;
    break;
  case 4:
    CurrentChannel->ODTTriMap = (UINT8 *) DrRDdr2ODTTri4D;
    break;
  default:
    CurrentChannel->ODTTriMap = (UINT8 *) DrRDdr2ODTTri2D;
  }

  CurrentChannel->DctEccDqsLike = 0x0504;
  CurrentChannel->DctEccDqsScale = 0;
  CurrentChannel->DctAddrTmg = AddrTmgCTL;
  CurrentChannel->DctOdcCtl = DctOdcCtl;
  CurrentChannel->SlowMode = SlowMode;

  return AGESA_SUCCESS;
}
예제 #14
0
파일: mmLvDdr3.c 프로젝트: B-Rich/coreboot
/**
 *
 *  Find the common supported voltage on all nodes, taken into account of the
 *  user option for performance and power saving.
 *
 *     @param[in,out]   *MemMainPtr   - Pointer to the MEM_MAIN_DATA_BLOCK
 *
 *     @return          TRUE -  No fatal error occurs.
 *     @return          FALSE - Fatal error occurs.
 */
BOOLEAN
MemMLvDdr3PerformanceEnhPre (
  IN OUT   MEM_MAIN_DATA_BLOCK *MemMainPtr
  )
{
  UINT8 Node;
  BOOLEAN RetVal;
  DIMM_VOLTAGE VDDIO;
  MEM_NB_BLOCK *NBPtr;
  MEM_PARAMETER_STRUCT *ParameterPtr;
  MEM_SHARED_DATA *mmSharedPtr;
  PLATFORM_POWER_POLICY PowerPolicy;
  UINT8 *PowerPolicyPtr;

  NBPtr = MemMainPtr->NBPtr;
  mmSharedPtr = MemMainPtr->mmSharedPtr;
  ParameterPtr = MemMainPtr->MemPtr->ParameterListPtr;
  PowerPolicyPtr = FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_MEMORY_POWER_POLICY, 0, 0, 0, NULL, NULL);
  if (PowerPolicyPtr != NULL) {
    PowerPolicy = (PLATFORM_POWER_POLICY) *PowerPolicyPtr;
    IDS_HDT_CONSOLE (MEM_FLOW, "\nPlatform overrides memory power policy");
  } else {
    PowerPolicy = MemMainPtr->MemPtr->PlatFormConfig->PlatformProfile.PlatformPowerPolicy;
  }

  IDS_OPTION_HOOK (IDS_MEMORY_POWER_POLICY, &PowerPolicy, &NBPtr->MemPtr->StdHeader);
  IDS_HDT_CONSOLE (MEM_FLOW, (PowerPolicy == Performance) ? "\nMaximize Performance\n" : "\nMaximize Battery Life\n");

  if (ParameterPtr->DDR3Voltage != VOLT_INITIAL) {
    mmSharedPtr->VoltageMap = VDDIO_DETERMINED;
    PutEventLog (AGESA_WARNING, MEM_WARNING_INITIAL_DDR3VOLT_NONZERO, 0, 0, 0, 0, &(NBPtr[BSP_DIE].MemPtr->StdHeader));
    SetMemError (AGESA_WARNING, NBPtr[BSP_DIE].MCTPtr);
    IDS_HDT_CONSOLE (MEM_FLOW, "Warning: Initial Value for VDDIO has been changed.\n");
    RetVal = TRUE;
  } else {
    RetVal = MemMLvDdr3 (MemMainPtr);

    VDDIO = ParameterPtr->DDR3Voltage;
    if (NBPtr->IsSupported[PerformanceOnly] || ((PowerPolicy == Performance) && (mmSharedPtr->VoltageMap != 0))) {
      // When there is no commonly supported voltage, do not optimize performance
      // For cases where we can maximize performance, do the following
      // When VDDIO is enforced, DDR3Voltage will be overriden by specific VDDIO
      // So cases with DDR3Voltage left to be VOLT_UNSUPPORTED will be open to maximizing performance.
      ParameterPtr->DDR3Voltage = VOLT_UNSUPPORTED;
    }

    IDS_OPTION_HOOK (IDS_ENFORCE_VDDIO, &(ParameterPtr->DDR3Voltage), &NBPtr->MemPtr->StdHeader);

    if (ParameterPtr->DDR3Voltage != VOLT_UNSUPPORTED) {
      // When Voltage is already determined, do not have further process to choose maximum frequency to optimize performance
      mmSharedPtr->VoltageMap = VDDIO_DETERMINED;
      IDS_HDT_CONSOLE (MEM_FLOW, "VDDIO is determined. No further optimization will be done.\n");
    } else {
      for (Node = 0; Node < MemMainPtr->DieCount; Node++) {
        NBPtr[Node].MaxFreqVDDIO[VOLT1_5_ENCODED_VAL] = UNSUPPORTED_DDR_FREQUENCY;
        NBPtr[Node].MaxFreqVDDIO[VOLT1_35_ENCODED_VAL] = UNSUPPORTED_DDR_FREQUENCY;
        NBPtr[Node].MaxFreqVDDIO[VOLT1_25_ENCODED_VAL] = UNSUPPORTED_DDR_FREQUENCY;
      }
      // Reprogram the leveling result as temporal candidate
      ParameterPtr->DDR3Voltage = VDDIO;
    }
  }

  ASSERT (ParameterPtr->DDR3Voltage != VOLT_UNSUPPORTED);
  return RetVal;
}
예제 #15
0
파일: mpmaxfreq.c 프로젝트: 0ida/coreboot
/**
 *
 *    A sub-function which extracts the value of max frequency supported from a input table and
 *    compares it with DCTPtr->Timings.TargetSpeed
 *
 *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
 *     @param[in]       *EntryOfTables     - Pointer to MEM_PSC_TABLE_BLOCK
 *
 *     @return          TRUE - Succeed in extracting the table value
 *     @return          FALSE - Fail to extract the table value
 *
 */
BOOLEAN
MemPGetMaxFreqSupported (
  IN OUT   MEM_NB_BLOCK *NBPtr,
  IN       MEM_PSC_TABLE_BLOCK *EntryOfTables
  )
{
  UINT8 i;
  UINT8 MaxDimmSlotPerCh;
  UINT8 MaxDimmPerCh;
  UINT8 NOD;
  UINT8 TableSize;
  PSCFG_TYPE Type;
  UINT16 CDN;
  UINT16 MaxFreqSupported;
  UINT16 *SpeedArray;
  UINT8 DDR3Voltage;
  UINT8 CurrentVoltage;
  DIMM_TYPE DimmType;
  CPU_LOGICAL_ID LogicalCpuid;
  UINT8 PackageType;
  BOOLEAN DisDct;
  UINT8 PsoMaskMaxFreq;
  UINT16 PsoMaskMaxFreq16;
  UINT8 NumDimmSlotInTable;
  UINT16 DimmPopInTable;
  PSCFG_MAXFREQ_ENTRY *TblPtr;
  CH_DEF_STRUCT *CurrentChannel;
  PSC_TBL_ENTRY **TblEntryOfMaxFreq;

  CurrentChannel = NBPtr->ChannelPtr;

  DisDct = FALSE;
  Type = PSCFG_MAXFREQ;
  TblPtr = NULL;
  TableSize = 0;
  PackageType = 0;
  NumDimmSlotInTable = 0;
  DimmPopInTable = 0;
  LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;
  SpeedArray = NULL;

  MaxDimmPerCh = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
  MaxDimmSlotPerCh = MaxDimmPerCh - GetMaxSolderedDownDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration,
                                                                       NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);

  if (CurrentChannel->RegDimmPresent != 0) {
    DimmType = RDIMM_TYPE;
  } else if (CurrentChannel->SODimmPresent != 0) {
    DimmType = SODIMM_TYPE;
  } else if (CurrentChannel->LrDimmPresent != 0) {
    DimmType = LRDIMM_TYPE;
  } else {
    DimmType = UDIMM_TYPE;
  }

  // Check if it is "SODIMM plus soldered-down DRAM" or "Soldered-down DRAM only" configuration,
  // DimmType is changed to 'SODWN_SODIMM_TYPE' if soldered-down DRAM exist
  if (MaxDimmSlotPerCh != MaxDimmPerCh) {
    // SODIMM plus soldered-down DRAM
    DimmType = SODWN_SODIMM_TYPE;
  } else if (FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_SOLDERED_DOWN_SODIMM_TYPE, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID, 0, NULL, NULL) != NULL) {
    // Soldered-down DRAM only
    DimmType = SODWN_SODIMM_TYPE;
    MaxDimmSlotPerCh = 0;
  }
  NOD = (UINT8) (MaxDimmSlotPerCh != 0) ? (1 << (MaxDimmSlotPerCh - 1)) : _DIMM_NONE;

  TblEntryOfMaxFreq = EntryOfTables->TblEntryOfMaxFreq;
  IDS_OPTION_HOOK (IDS_GET_STRETCH_FREQUENCY_LIMIT, &TblEntryOfMaxFreq, &NBPtr->MemPtr->StdHeader);

  i = 0;
  // Obtain table pointer, table size, Logical Cpuid and PSC type according to Dimm, NB and package type.
  while (TblEntryOfMaxFreq[i] != NULL) {
    if (((TblEntryOfMaxFreq[i])->Header.DimmType & DimmType) != 0) {
      if (((TblEntryOfMaxFreq[i])->Header.NumOfDimm & NOD) != 0) {
        //
        // Determine if this is the expected NB Type
        //
        LogicalCpuid = (TblEntryOfMaxFreq[i])->Header.LogicalCpuid;
        PackageType = (TblEntryOfMaxFreq[i])->Header.PackageType;
        if (MemPIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
          TblPtr = (PSCFG_MAXFREQ_ENTRY *) ((TblEntryOfMaxFreq[i])->TBLPtr);
          TableSize = (TblEntryOfMaxFreq[i])->TableSize;
          Type = (TblEntryOfMaxFreq[i])->Header.PSCType;
          break;
        }
      }
    }
    i++;
  }

  // Check whether no table entry is found.
  if (TblEntryOfMaxFreq[i] == NULL) {
    IDS_HDT_CONSOLE (MEM_FLOW, "\nDCT %d: No MaxFreq table. This channel will be disabled.\n", NBPtr->Dct);
    return FALSE;
  }

  MaxFreqSupported = UNSUPPORTED_DDR_FREQUENCY;
  CDN = 0;
  DDR3Voltage = (UINT8) CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage);

  // Construct the condition value
  ((CDNMaxFreq *)&CDN)->Dimms = CurrentChannel->Dimms;
  if (Type == PSCFG_MAXFREQ) {
    for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) {
      if ((CurrentChannel->DimmSRPresent & (UINT8) (1 << i)) != 0) {
        ((CDNMaxFreq *)&CDN)->SR += 1;
      }
      if ((CurrentChannel->DimmDrPresent & (UINT16) (1 << i)) != 0) {
        ((CDNMaxFreq *)&CDN)->DR += 1;
      }
      if ((CurrentChannel->DimmQrPresent & (UINT16) (1 << i)) != 0) {
        if (i < 2) {
          ((CDNMaxFreq *)&CDN)->QR += 1;
        }
      }
    }
  } else {
    ((CDNLMaxFreq *)&CDN)->LR = CurrentChannel->Dimms;
  }

  for (i = 0; i < TableSize; i++) {
    NumDimmSlotInTable = TblPtr->MAXFREQ_ENTRY.DimmSlotPerCh;
    DimmPopInTable = (Type == PSCFG_MAXFREQ) ? TblPtr->MAXFREQ_ENTRY.CDN : ((PSCFG_LR_MAXFREQ_ENTRY *)TblPtr)->LR_MAXFREQ_ENTRY.CDN;
    if (((NumDimmSlotInTable & NOD) != 0) && (CDN == DimmPopInTable)) {
      if (Type == PSCFG_MAXFREQ) {
        SpeedArray = TblPtr->MAXFREQ_ENTRY.Speed;
      } else {
        SpeedArray = ((PSCFG_LR_MAXFREQ_ENTRY *)TblPtr)->LR_MAXFREQ_ENTRY.Speed;
      }
      break;
    }
    TblPtr++;
  }

  PsoMaskMaxFreq16 = MemPProceedTblDrvOverride (NBPtr, NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_TBLDRV_SPEEDLIMIT);
  if ((PsoMaskMaxFreq16 & INVALID_CONFIG_FLAG) == 0) {
    PsoMaskMaxFreq = (UINT8) PsoMaskMaxFreq16;
    if (PsoMaskMaxFreq != 0) {
      SpeedArray = NBPtr->PsPtr->SpeedLimit;
    }
  } else {
    SpeedArray = NULL;
  }

  if (SpeedArray != NULL) {
    if (NBPtr->SharedPtr->VoltageMap != VDDIO_DETERMINED) {
      IDS_HDT_CONSOLE (MEM_FLOW, "\nCheck speed supported for each VDDIO for Node%d DCT%d: ", NBPtr->Node, NBPtr->Dct);
      for (CurrentVoltage = VOLT1_5_ENCODED_VAL; CurrentVoltage <= VOLT1_25_ENCODED_VAL; CurrentVoltage ++) {
        if (NBPtr->SharedPtr->VoltageMap & (1 << CurrentVoltage)) {
          IDS_HDT_CONSOLE (MEM_FLOW, "%s -> %dMHz ", (CurrentVoltage == VOLT1_5_ENCODED_VAL) ? "1.5V" : ((CurrentVoltage == VOLT1_35_ENCODED_VAL) ? "1.35V" : "1.25V"), SpeedArray[CurrentVoltage]);
          if (NBPtr->DCTPtr->Timings.TargetSpeed > SpeedArray[CurrentVoltage]) {
            MaxFreqSupported = SpeedArray[CurrentVoltage];
          } else {
            MaxFreqSupported = NBPtr->DCTPtr->Timings.TargetSpeed;
          }
          if (NBPtr->MaxFreqVDDIO[CurrentVoltage] > MaxFreqSupported) {
            NBPtr->MaxFreqVDDIO[CurrentVoltage] = MaxFreqSupported;
          }
        } else {
          NBPtr->MaxFreqVDDIO[CurrentVoltage] = 0;
        }
      }
      IDS_HDT_CONSOLE (MEM_FLOW, "\n");
    }
    ASSERT (DDR3Voltage <= VOLT1_25_ENCODED_VAL);
    MaxFreqSupported = SpeedArray[DDR3Voltage];
  }

  if (MaxFreqSupported == UNSUPPORTED_DDR_FREQUENCY) {
    // No entry in the table for current dimm population is found
    IDS_HDT_CONSOLE (MEM_FLOW, "\nDCT %d: No entry is found in the Max Frequency table\n", NBPtr->Dct);
    DisDct = TRUE;
  } else if (MaxFreqSupported != 0) {
    if (NBPtr->DCTPtr->Timings.TargetSpeed > MaxFreqSupported) {
      NBPtr->DCTPtr->Timings.TargetSpeed = MaxFreqSupported;
    }
  } else if (NBPtr->SharedPtr->VoltageMap == VDDIO_DETERMINED) {
    // Dimm population is not supported at current voltage
    // Also if there is no performance optimization, disable the DCT
    DisDct = TRUE;
  }

  if (DisDct) {
    NBPtr->DCTPtr->Timings.DimmExclude |= NBPtr->DCTPtr->Timings.DctDimmValid;
    PutEventLog (AGESA_ERROR, MEM_ERROR_UNSUPPORTED_DIMM_CONFIG, NBPtr->Node, NBPtr->Dct, NBPtr->Channel, 0, &NBPtr->MemPtr->StdHeader);
    SetMemError (AGESA_ERROR, NBPtr->MCTPtr);
    // Change target speed to highest value so it won't affect other channels when leveling frequency across the node.
    NBPtr->DCTPtr->Timings.TargetSpeed = UNSUPPORTED_DDR_FREQUENCY;
  }

  return TRUE;
}
예제 #16
0
파일: mps2d.c 프로젝트: fishbaoz/edk2ml
/**
 *
 *    A sub-function which determine if 2D should be run
 *    from a input table
 *
 *     @param[in,out]   *NBPtr   - Pointer to the MEM_NB_BLOCK
 *     @param[in]       *EntryOfTables     - Pointer to MEM_PSC_TABLE_BLOCK
 *
 *     @return          TRUE - Table values can be extracted per dimm population and ranks type.
 *     @return          FALSE - Table values cannot be extracted per dimm population and ranks type.
 *
 */
BOOLEAN
MemPGetS2D (
  IN OUT   MEM_NB_BLOCK *NBPtr,
  IN       MEM_PSC_TABLE_BLOCK *EntryOfTables
  )
{

  UINT8 i;
  UINT8 MaxDimmPerCh;
  UINT8 MaxDimmSlotPerCh;
  UINT8 NOD;
  UINT8 TableSize;
  UINT32 CurDDRrate;
  UINT8 DDR3Voltage;
  UINT16 RankTypeOfPopulatedDimm;
  UINT16 RankTypeInTable;
  BOOLEAN FoundValue;
  DIMM_TYPE DimmType;
  CPU_LOGICAL_ID LogicalCpuid;
  UINT8 PackageType;
  PSCFG_S2D_ENTRY *TblPtr;
  CH_DEF_STRUCT *CurrentChannel;
  UINT16 P2dTraingOveride;

  CurrentChannel = NBPtr->ChannelPtr;

  TblPtr = NULL;
  TableSize = 0;
  PackageType = 0;
  LogicalCpuid.Family = AMD_FAMILY_UNKNOWN;

  MaxDimmPerCh = GetMaxDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration, NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);
  MaxDimmSlotPerCh = MaxDimmPerCh - GetMaxSolderedDownDimmsPerChannel (NBPtr->RefPtr->PlatformMemoryConfiguration,
                                                                       NBPtr->MCTPtr->SocketId, CurrentChannel->ChannelID);

  if (CurrentChannel->RegDimmPresent != 0) {
    DimmType = RDIMM_TYPE;
  } else if (CurrentChannel->SODimmPresent != 0) {
    DimmType = SODIMM_TYPE;
  } else if (CurrentChannel->LrDimmPresent != 0) {
    DimmType = LRDIMM_TYPE;
  } else {
    DimmType = UDIMM_TYPE;
  }

  // Check if it is "SODIMM plus soldered-down DRAM" or "Soldered-down DRAM only" configuration,
  // DimmType is changed to 'SODWN_SODIMM_TYPE' if soldered-down DRAM exist
  if (MaxDimmSlotPerCh != MaxDimmPerCh) {
    // SODIMM plus soldered-down DRAM
    DimmType = SODWN_SODIMM_TYPE;
  } else if (FindPSOverrideEntry (NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_SOLDERED_DOWN_SODIMM_TYPE, NBPtr->MCTPtr->SocketId, NBPtr->ChannelPtr->ChannelID, 0, NULL, NULL) != NULL) {
    // Soldered-down DRAM only
    DimmType = SODWN_SODIMM_TYPE;
    MaxDimmSlotPerCh = 0;
  }
  NOD = (UINT8) (MaxDimmSlotPerCh != 0) ? (1 << (MaxDimmSlotPerCh - 1)) : _DIMM_NONE;

  i = 0;
  // Obtain table pointer, table size, Logical Cpuid and PSC type according to Dimm, NB and package type.
  while (EntryOfTables->TblEntryOfS2D[i] != NULL) {
    if (((EntryOfTables->TblEntryOfS2D[i])->Header.DimmType & DimmType) != 0) {
      if (((EntryOfTables->TblEntryOfS2D[i])->Header.NumOfDimm & NOD) != 0) {
        //
        // Determine if this is the expected NB Type
        //
        LogicalCpuid = (EntryOfTables->TblEntryOfS2D[i])->Header.LogicalCpuid;
        PackageType = (EntryOfTables->TblEntryOfS2D[i])->Header.PackageType;
        if (MemPIsIdSupported (NBPtr, LogicalCpuid, PackageType)) {
          TblPtr = (PSCFG_S2D_ENTRY *) ((EntryOfTables->TblEntryOfS2D[i])->TBLPtr);
          TableSize = (EntryOfTables->TblEntryOfS2D[i])->TableSize;
          break;
        }
      }
    }
    i++;
  }

  // Check whether no table entry is found.
  if (EntryOfTables->TblEntryOfS2D[i] == NULL) {
    IDS_HDT_CONSOLE (MEM_FLOW, "\nNo 2D training Config table\n");
    return FALSE;
  }
  CurDDRrate = (UINT32) (1 << (CurrentChannel->DCTPtr->Timings.Speed / 66));
  DDR3Voltage = (UINT8) (1 << CONVERT_VDDIO_TO_ENCODED (NBPtr->RefPtr->DDR3Voltage));
  RankTypeOfPopulatedDimm = MemPGetPsRankType (CurrentChannel);
  FoundValue = FALSE;
  for (i = 0; i < TableSize; i++) {
    MemPConstructRankTypeMap ((UINT16) TblPtr->Dimm0, (UINT16) TblPtr->Dimm1, (UINT16) TblPtr->Dimm2, &RankTypeInTable);
    if ((TblPtr->DimmPerCh & NOD) != 0) {
      if ((TblPtr->DDRrate & CurDDRrate) != 0) {
        if ((TblPtr->VDDIO & DDR3Voltage) != 0) {
          if ((RankTypeInTable & RankTypeOfPopulatedDimm) == RankTypeOfPopulatedDimm) {
            if (TblPtr->Enable2D == 1) {
              FoundValue = TRUE;
              break;
            }
          }
        }
      }
    }
    TblPtr++;
  }
  P2dTraingOveride = MemPProceedTblDrvOverride (NBPtr, NBPtr->RefPtr->PlatformMemoryConfiguration, PSO_TBLDRV_2D_TRAINING);
  if (P2dTraingOveride != 0) {
    if (NBPtr->Override2DTraining) {
      FoundValue = TRUE;
    } else {
      FoundValue = FALSE;
    }
  }
  //
  // If there is no entry, check if overriding 2D training existed. If not, show no entry found.
  //
  if (FoundValue == FALSE || ((P2dTraingOveride & INVALID_CONFIG_FLAG) != 0)) {
    IDS_HDT_CONSOLE (MEM_FLOW, "\nNo 2D training config entries\n");
    return FALSE;
  } else {
    return TRUE;
  }
}