/** * * This function matches a particular Rank Type Mask to the installed * DIMM configuration on the provided channel. * * @param[in] *CurrentChannel Pointer to CH_DEF_STRUCT * @param[in] RankType Mask of rank type to match * * @return BOOLEAN - TRUE : Rank types match * FALSE: Rank types do not match * */ BOOLEAN STATIC MemCheckRankType ( IN CH_DEF_STRUCT *CurrentChannel, IN UINT16 RankType ) { BOOLEAN Result; UINT8 i; UINT16 DIMMRankType; DIMMRankType = MemAGetPsRankType (CurrentChannel); Result = TRUE; for (i = 0; i < MAX_DIMMS_PER_CHANNEL; i++) { if ( ((DIMMRankType & (0x0F << (i << 2))) + (RankType & (0x0F << (i << 2)))) != 0) { Result &= (((DIMMRankType & (0x0F << (i << 2))) & ( RankType & ( 0x0F << ( i << 2)))) != 0); } if (!Result) { break; } } return Result; }
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; }
AGESA_STATUS MemAGetPsCfgUNi3 ( IN OUT MEM_DATA_STRUCT *MemData, IN UINT8 SocketID, IN OUT CH_DEF_STRUCT *CurrentChannel ) { STATIC CONST PSCFG_ENTRY PSCfg1Dimm[] = { {DDR800_FREQUENCY, 0x10, 0x003B0000, 0x20113222}, {DDR1066_FREQUENCY, 0x10, 0x00380000, 0x20113222}, {DDR1333_FREQUENCY, 0x10, 0x00360000, 0x20113222}, {DDR1600_FREQUENCY, 0x10, 0x00340000, 0x20113222} }; STATIC CONST PSCFG_ENTRY PSCfg2Dimm[] = { {DDR800_FREQUENCY, 0xFF, 0x00390039, 0x20223323}, {DDR1066_FREQUENCY, 0xFF, 0x00350037, 0x20223323}, {DDR1333_FREQUENCY, 0xFF, 0x00000035, 0x20223323}, {DDR1600_FREQUENCY, 0xFF, 0x00000033, 0x20223323} }; STATIC CONST ADV_R_PSCFG_WL_ODT_ENTRY PSCfgDIMMWlODT[] = { {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} }; UINT16 i; UINT16 j; UINT8 Loads; UINT8 Dimms; UINT16 Speed; UINT16 DIMMRankType; UINT16 _DIMMRankType; UINT32 AddrTmgCTL; UINT32 DctOdcCtl; UINT8 PhyWLODT[4]; BOOLEAN SlowMode; UINT8 DimmTpMatch; ASSERT (MemData != 0); ASSERT (CurrentChannel != 0); AddrTmgCTL = 0; DctOdcCtl = 0; PhyWLODT[0] = 0x0F; PhyWLODT[1] = 0x0F; PhyWLODT[2] = 0x0F; PhyWLODT[3] = 0x0F; 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->RegDimmPresent != 0) || (CurrentChannel->SODimmPresent != 0)) { return AGESA_UNSUPPORTED; } // Prepare inputs 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 if ((Speed == DDR1600_FREQUENCY) && (Dimms == 1) && (Loads >= 16)) { SlowMode = TRUE; // 2T } else { SlowMode = FALSE; // 1T } if (Dimms == 1) { for (i = 0; i < GET_SIZE_OF (PSCfg1Dimm); i++) { if (Speed == PSCfg1Dimm[i].Speed) { if (Loads >= PSCfg1Dimm[i].Loads) { AddrTmgCTL = PSCfg1Dimm[i].AddrTmg; DctOdcCtl = PSCfg1Dimm[i].Odc; } else { DctOdcCtl = 0x20113222; } break; } } ASSERT (i < GET_SIZE_OF (PSCfg1Dimm)); } else { for (i = 0; i < GET_SIZE_OF (PSCfg2Dimm); i++) { if (Speed == PSCfg2Dimm[i].Speed) { if (Loads <= PSCfg2Dimm[i].Loads) { AddrTmgCTL = PSCfg2Dimm[i].AddrTmg; DctOdcCtl = PSCfg2Dimm[i].Odc; break; } } } ASSERT (i < GET_SIZE_OF (PSCfg2Dimm)); } // 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; } } CurrentChannel->MemClkDisMap = (UINT8 *) NiUDdr3CLKDis; CurrentChannel->CKETriMap = (UINT8 *) NiUDdr3CKETri; CurrentChannel->ODTTriMap = (UINT8 *) NiUDdr3ODTTri; CurrentChannel->ChipSelTriMap = (UINT8 *) NiUDdr3CSTri; CurrentChannel->DctEccDqsLike = 0x0403; CurrentChannel->DctEccDqsScale = 0x70; 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; }