/** * * 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; } }
/** * * 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; } }
/** * * 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; } }
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; }
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; }
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; }
/** * * 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; }
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; }
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; }
/** * * 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; }
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)); }
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); }
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; }
/** * * 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; }
/** * * 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; }
/** * * 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; } }