AGESA_STATUS GfxFmCalculateClock ( IN UINT8 Did, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 MainPllFreq10kHz; MainPllFreq10kHz = GfxLibGetMainPllFreq (StdHeader) * 100; return GfxLibCalculateClk (Did, MainPllFreq10kHz); }
/** * Family specific fuse table patch * Is's correct behavior if we would have 4 states, it would be * PP_FUSE_ARRAY->LclkDpmDid[0] - Goes to State 5 * PP_FUSE_ARRAY->LclkDpmDid[1] - Goes to State 6 * PP_FUSE_ARRAY->LclkDpmDid[2] - Goes to State 7 * If we would have 4 states it would be * PP_FUSE_ARRAY->LclkDpmDid[0] - Goes to State 4 * PP_FUSE_ARRAY->LclkDpmDid[1] - Goes to State 5 * PP_FUSE_ARRAY->LclkDpmDid[2] - Goes to State 6 * PP_FUSE_ARRAY->LclkDpmDid[3] - Goes to State 7 * * @param[in] PpFuseArray Pointer to PP_FUSE_ARRAY * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS */ VOID NbFmFuseAdjustFuseTablePatch ( IN OUT PP_FUSE_ARRAY *PpFuseArray, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 LclkDpmMode; UINT8 SwSatateIndex; UINT8 MaxSclkIndex; UINT8 DpmStateIndex; UINT8 CurrentSclkDpmDid; CPU_LOGICAL_ID LogicalId; D18F3x15C_STRUCT D18F3x15C; LclkDpmMode = GnbBuildOptions.LclkDpmEn ? LclkDpmRcActivity : LclkDpmDisabled; GetLogicalIdOfCurrentCore (&LogicalId, StdHeader); if ((LogicalId.Revision & (AMD_F12_LN_A0 | AMD_F12_LN_A1)) != 0) { LclkDpmMode = LclkDpmDisabled; } IDS_OPTION_HOOK (IDS_GNB_LCLK_DPM_EN, &LclkDpmMode, StdHeader); // Read Sclk VID GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS), AccessWidth32, &D18F3x15C.Value, StdHeader ); PpFuseArray->SclkVid[0] = (UINT8) (D18F3x15C.Field.SclkVidLevel0); PpFuseArray->SclkVid[1] = (UINT8) (D18F3x15C.Field.SclkVidLevel1); PpFuseArray->SclkVid[2] = (UINT8) (D18F3x15C.Field.SclkVidLevel2); PpFuseArray->SclkVid[3] = (UINT8) (D18F3x15C.Field.SclkVidLevel3); //For all CPU rev LclkDpmValid[3] = 0 PpFuseArray->LclkDpmValid[3] = 0; PpFuseArray->LclkDpmVid[3] = 0; PpFuseArray->LclkDpmDid[3] = 0; // For LCLKDPM set LclkDpmVid[0] = 0, no matter if LCLK DMP enable or disable. PpFuseArray->LclkDpmVid[0] = 0; if (LclkDpmMode != LclkDpmRcActivity) { //If LCLK DPM disable (LclkDpmMode != LclkDpmRcActivity) // - LclkDpmDid[1,2] = LclkDpmDid [0], LclkDpmVid[1,2] = LclkDpmVid[0] // - Execute LCLK DPM init PpFuseArray->LclkDpmVid[1] = PpFuseArray->LclkDpmVid[0]; PpFuseArray->LclkDpmVid[2] = PpFuseArray->LclkDpmVid[0]; PpFuseArray->LclkDpmDid[1] = PpFuseArray->LclkDpmDid[0]; PpFuseArray->LclkDpmDid[2] = PpFuseArray->LclkDpmDid[0]; IDS_HDT_CONSOLE (NB_MISC, " F12 LCLK DPM Mode Disable -- use DPM0 fusing\n"); } else { // If LCLK DPM enabled // - use fused values for LclkDpmDid[0,1,2] and appropriate voltage // - Execute LCLK DPM init PpFuseArray->LclkDpmVid[2] = PpFuseArray->PcieGen2Vid; if (GfxLibIsControllerPresent (StdHeader)) { //VID index = VID index associated with highest SCLK DPM state in the Powerplay state where Label_Performance=1 // This would ignore the UVD case (where Label_Performance would be 0). for (SwSatateIndex = 0 ; SwSatateIndex < PP_FUSE_MAX_NUM_SW_STATE; SwSatateIndex++) { if (PpFuseArray->PolicyLabel[SwSatateIndex] == POLICY_LABEL_PERFORMANCE) { break; } } MaxSclkIndex = 0; CurrentSclkDpmDid = 0xff; ASSERT (PpFuseArray->SclkDpmValid[SwSatateIndex] != 0); for (DpmStateIndex = 0; DpmStateIndex < PP_FUSE_MAX_NUM_DPM_STATE; DpmStateIndex++) { if ((PpFuseArray->SclkDpmValid[SwSatateIndex] & (1 << DpmStateIndex)) != 0) { if (PpFuseArray->SclkDpmDid[DpmStateIndex] < CurrentSclkDpmDid) { CurrentSclkDpmDid = PpFuseArray->SclkDpmDid[DpmStateIndex]; MaxSclkIndex = DpmStateIndex; } } } PpFuseArray->LclkDpmVid[1] = PpFuseArray->SclkDpmVid[MaxSclkIndex]; } else { PpFuseArray->LclkDpmVid[1] = PpFuseArray->LclkDpmVid[0]; PpFuseArray->LclkDpmDid[1] = PpFuseArray->LclkDpmDid[0]; } // - use fused values for LclkDpmDid[0,1,2] and appropriate voltage //Keep using actual fusing IDS_HDT_CONSOLE (NB_MISC, " LCLK DPM use actual fusing.\n"); } //Patch SclkThermDid to 200Mhz if not fused if (PpFuseArray->SclkThermDid == 0) { PpFuseArray->SclkThermDid = GfxLibCalculateDid (200 * 100, GfxLibGetMainPllFreq (StdHeader) * 100); } }
AGESA_STATUS NbFmInitLclkDpmRcActivity ( IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS Status; PP_FUSE_ARRAY *PpFuseArray; INT8 Index; UINTN LclkState; Status = AGESA_SUCCESS; IDS_HDT_CONSOLE (GNB_TRACE, "NbFmInitLclkDpmRcActivity F14 Enter\n"); PpFuseArray = GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, StdHeader); if (PpFuseArray != NULL) { UINT32 ActivityThreshold [8]; UINT16 SamplingPeriod [10]; UINT8 LclkScalingDid [4]; UINT8 LclkScalingVid [4]; UINT32 LclkDpmValid; UINT32 MainPllVcoKHz; LibAmdMemFill (&ActivityThreshold[0], 0, sizeof (ActivityThreshold), StdHeader); LibAmdMemFill (&SamplingPeriod[0], 0, sizeof (SamplingPeriod), StdHeader); MainPllVcoKHz = GfxLibGetMainPllFreq (StdHeader) * 100; LclkDpmValid = 0; LclkState = 7; for (Index = 3; Index >= 0; Index--) { if (PpFuseArray->LclkDpmValid [Index] != 0) { // Set valid DPM state LclkDpmValid |= (1 << (LclkState)); // Set LCLK scaling DID LclkScalingDid [7 - LclkState] = PpFuseArray->LclkDpmDid [Index]; // Set LCLK scaling VID LclkScalingVid [7 - LclkState] = PpFuseArray->LclkDpmVid [Index]; // Set sampling period SamplingPeriod [LclkState] = 0xC350; // Changed from 0xC350 to 0x1388 for DPM 0 if (Index == 0) { SamplingPeriod [LclkState] = 0x1388; } // Set activity threshold from BKDG: // Raising -- ActivityThreshold [LclkState] = ((102 * (GfxLibCalculateClk (LclkScalingDid [7 - LclkState], MainPllVcoKHz) / 100)) - 10) / 10; // Lowering -- ActivityThreshold [LclkState] |= (((407 * (GfxLibCalculateClk (LclkScalingDid [7 - LclkState], MainPllVcoKHz) / 100)) + 99) / 10) << 16; // For ON specific enable LCLK DPM : ActivityThreshold [LclkState] = LclkDpmActivityThresholdTable [Index]; IDS_HDT_CONSOLE (GNB_TRACE, "Fused State Index:%d LCLK DPM State [%d]: LclkScalingDid - 0x%x, ActivityThreshold - 0x%x, SamplingPeriod - 0x%x\n", Index, LclkState, LclkScalingDid [7 - LclkState], ActivityThreshold [LclkState], SamplingPeriod [LclkState] ); LclkState--; } } if (LclkState != 7) { SMUx33_STRUCT SMUx33; SMUx0B_x8434_STRUCT SMUx0B_x8434; FCRxFF30_01E4_STRUCT FCRxFF30_01E4; UINT8 CurrentUnit; UINT16 FinalUnit; UINT16 FinalPeriod; UINT32 Freq; UINT32 FreqDelta; UINT32 Value; ASSERT (LclkScalingDid [0] != 0); FreqDelta = 0xffffffff; FinalPeriod = 0; FinalUnit = 0; Freq = (65535 * 100 * 100) / GfxLibCalculateClk (LclkScalingDid [0], MainPllVcoKHz); for (CurrentUnit = 0; CurrentUnit < 16; CurrentUnit++) { UINT32 CurrentFreqDelta; UINT32 CurrentPeriod; UINT32 Temp; Temp = GnbLibPowerOf (4, CurrentUnit); CurrentPeriod = Freq / Temp; if (CurrentPeriod <= 0xFFFF) { CurrentFreqDelta = Freq - Temp * CurrentPeriod; if (FreqDelta > CurrentFreqDelta) { FinalUnit = CurrentUnit; FinalPeriod = (UINT16) CurrentPeriod; FreqDelta = CurrentFreqDelta; } } } //Process to enablement LCLK DPM States NbSmuIndirectRead (SMUx33_ADDRESS, AccessWidth32, &SMUx33.Value, StdHeader); SMUx33.Field.BusyCntSel = 0x3; SMUx33.Field.LclkActMonUnt = FinalUnit; SMUx33.Field.LclkActMonPrd = FinalPeriod; NbSmuIndirectWrite (SMUx33_ADDRESS, AccessS3SaveWidth32, &SMUx33.Value, StdHeader); SMUx0B_x8434.Value = 0; SMUx0B_x8434.Field.LclkDpmType = 0x1; SMUx0B_x8434.Field.LclkDpmEn = 0x1; SMUx0B_x8434.Field.LclkTimerPeriod = 0x0C350; SMUx0B_x8434.Field.LclkTimerPrescalar = 0x1; NbSmuRcuRegisterWrite ( SMUx0B_x8434_ADDRESS, &SMUx0B_x8434.Value, 1, TRUE, StdHeader ); NbSmuRcuRegisterWrite ( 0x84AC, &LclkDpmCacTable[0], sizeof (LclkDpmCacTable) / sizeof (UINT32), TRUE, StdHeader ); // Program activity threshold IDS_HDT_CONSOLE (GNB_TRACE, "ActivityThreshold[4] - 0x%x ActivityThreshold[5] - 0x%x ActivityThreshold[6] - 0x%x ActivityThreshold[7] - 0x%x\n", ActivityThreshold[4], ActivityThreshold[5], ActivityThreshold[6], ActivityThreshold [7] ); NbSmuRcuRegisterWrite ( SMUx0B_x8470_ADDRESS, &ActivityThreshold[4], 4, TRUE, StdHeader ); // Program sampling period for (Index = 0; Index < (sizeof (SamplingPeriod) / sizeof (SamplingPeriod[0])); Index = Index + 2) { UINT16 Temp; Temp = SamplingPeriod[Index]; SamplingPeriod[Index] = SamplingPeriod[Index + 1]; SamplingPeriod[Index + 1] = Temp; } IDS_HDT_CONSOLE (GNB_TRACE, "SamplingPeriod[4] - 0x%x SamplingPeriod[5] - 0x%x SamplingPeriod[6] - 0x%x SamplingPeriod[7] - 0x%x \n", SamplingPeriod[4], SamplingPeriod[5], SamplingPeriod[6], SamplingPeriod[7] ); NbSmuRcuRegisterWrite ( SMUx0B_x8440_ADDRESS, (UINT32*) &SamplingPeriod[4], 2, TRUE, StdHeader ); // Program LCK scaling DID NbSmuRcuRegisterWrite ( SMUx0B_x848C_ADDRESS, (UINT32*) &LclkScalingDid[0], 1, TRUE, StdHeader ); // Program LCK scaling VID NbSmuRcuRegisterWrite ( SMUx0B_x8498_ADDRESS, (UINT32*) &LclkScalingVid[0], 1, TRUE, StdHeader ); // Program valid LCLK DPM states LclkDpmValid = NbFmDpmStateBootupInit (LclkDpmValid, StdHeader); NbSmuRcuRegisterWrite ( SMUx0B_x8490_ADDRESS, &LclkDpmValid, 1, TRUE, StdHeader ); //Setup Activity Monitor Coefficients Value = (0x24 << SMUx35_DownTrendCoef_OFFSET) | (0x24 << SMUx35_UpTrendCoef_OFFSET); NbSmuIndirectWrite (SMUx35_ADDRESS, AccessS3SaveWidth32, &Value, StdHeader); Value = (0x22 << SMUx35_DownTrendCoef_OFFSET) | (0x22 << SMUx35_UpTrendCoef_OFFSET); for (Index = SMUx37_ADDRESS; Index <= SMUx51_ADDRESS; Index = Index + 2) { NbSmuIndirectWrite (Index, AccessS3SaveWidth32, &Value, StdHeader); } // Enable LCLK DPM as voltage client NbSmuSrbmRegisterRead (FCRxFF30_01E4_ADDRESS, &FCRxFF30_01E4.Value, StdHeader); FCRxFF30_01E4.Field.VoltageChangeEn = 0x1; NbSmuSrbmRegisterWrite (FCRxFF30_01E4_ADDRESS, &FCRxFF30_01E4.Value, TRUE, StdHeader); // Start LCLK service NbSmuServiceRequest (0x8, TRUE, StdHeader); } } else { IDS_HDT_CONSOLE (GNB_TRACE, " ERROR! Cannot locate fuse table\n"); Status = AGESA_ERROR; } IDS_HDT_CONSOLE (GNB_TRACE, "NbFmInitLclkDpmRcActivity F14 Exit [0x%x]\n", Status); return Status; }
/** * Build integrated info table * * * * @param[in] Gfx Gfx configuration info * @retval AGESA_STATUS */ AGESA_STATUS GfxIntegratedInfoTableInit ( IN GFX_PLATFORM_CONFIG *Gfx ) { AGESA_STATUS Status; AGESA_STATUS AgesaStatus; ATOM_FUSION_SYSTEM_INFO_V1 SystemInfoV1Table; PP_FUSE_ARRAY *PpFuseArray; PCIe_PLATFORM_CONFIG *Pcie; UINT32 IntegratedInfoAddress; ATOM_PPLIB_POWERPLAYTABLE3 *PpTable; UINT8 Channel; AgesaStatus = AGESA_SUCCESS; IDS_HDT_CONSOLE (GNB_TRACE, "GfxIntegratedInfoTableInit Enter\n"); LibAmdMemFill (&SystemInfoV1Table, 0x00, sizeof (ATOM_FUSION_SYSTEM_INFO_V1), GnbLibGetHeader (Gfx)); SystemInfoV1Table.sIntegratedSysInfo.sHeader.usStructureSize = sizeof (ATOM_INTEGRATED_SYSTEM_INFO_V6); ASSERT (SystemInfoV1Table.sIntegratedSysInfo.sHeader.usStructureSize == 512); SystemInfoV1Table.sIntegratedSysInfo.sHeader.ucTableFormatRevision = 1; SystemInfoV1Table.sIntegratedSysInfo.sHeader.ucTableContentRevision = 6; SystemInfoV1Table.sIntegratedSysInfo.ulDentistVCOFreq = GfxLibGetMainPllFreq (GnbLibGetHeader (Gfx)) * 100; SystemInfoV1Table.sIntegratedSysInfo.ulBootUpUMAClock = Gfx->UmaInfo.MemClock * 100; SystemInfoV1Table.sIntegratedSysInfo.usRequestedPWMFreqInHz = Gfx->LcdBackLightControl; SystemInfoV1Table.sIntegratedSysInfo.ucUMAChannelNumber = ((Gfx->UmaInfo.UmaAttributes & UMA_ATTRIBUTE_INTERLEAVE) == 0) ? 1 : 2; SystemInfoV1Table.sIntegratedSysInfo.ucMemoryType = 3; //DDR3 SystemInfoV1Table.sIntegratedSysInfo.ulBootUpEngineClock = 200 * 100; //Set default engine clock to 200MhZ SystemInfoV1Table.sIntegratedSysInfo.usBootUpNBVoltage = GfxLibMaxVidIndex (GnbLibGetHeader (Gfx)); SystemInfoV1Table.sIntegratedSysInfo.ulMinEngineClock = GfxLibGetMinSclk (GnbLibGetHeader (Gfx)); SystemInfoV1Table.sIntegratedSysInfo.usPanelRefreshRateRange = Gfx->DynamicRefreshRate; SystemInfoV1Table.sIntegratedSysInfo.usLvdsSSPercentage = Gfx->LvdsSpreadSpectrum; SystemInfoV1Table.sIntegratedSysInfo.usLvdsSSpreadRateIn10Hz = Gfx->LvdsSpreadSpectrumRate; SystemInfoV1Table.sIntegratedSysInfo.usPCIEClkSSPercentage = Gfx->PcieRefClkSpreadSpectrum; // SystemInfoV1Table.sIntegratedSysInfo.ucLvdsMisc = Gfx->LvdsMiscControl.Value; //Locate PCIe configuration data to get definitions of display connectors SystemInfoV1Table.sIntegratedSysInfo.sExtDispConnInfo.sHeader.usStructureSize = sizeof (ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO); SystemInfoV1Table.sIntegratedSysInfo.sExtDispConnInfo.sHeader.ucTableFormatRevision = 1; SystemInfoV1Table.sIntegratedSysInfo.sExtDispConnInfo.sHeader.ucTableContentRevision = 1; SystemInfoV1Table.sIntegratedSysInfo.sExtDispConnInfo.uc3DStereoPinId = Gfx->Gnb3dStereoPinIndex; ASSERT ((Gfx->UmaInfo.UmaAttributes & (UMA_ATTRIBUTE_ON_DCT0 | UMA_ATTRIBUTE_ON_DCT1)) != 0); if ((Gfx->UmaInfo.UmaAttributes & UMA_ATTRIBUTE_ON_DCT0) != 0) { Channel = 0; } else { Channel = 1; } if (GfxLibGetCsrPhySrPllPdMode (Channel, GnbLibGetHeader (Gfx)) != 0) { SystemInfoV1Table.sIntegratedSysInfo.ulSystemConfig |= BIT2; } if (GfxLibGetDisDllShutdownSR (Channel, GnbLibGetHeader (Gfx)) == 0) { SystemInfoV1Table.sIntegratedSysInfo.ulSystemConfig |= BIT1; } Status = PcieLocateConfigurationData (GnbLibGetHeader (Gfx), &Pcie); ASSERT (Status == AGESA_SUCCESS); AGESA_STATUS_UPDATE (Status, AgesaStatus); if (Status == AGESA_SUCCESS) { Status = GfxIntegratedEnumerateAllConnectors ( &SystemInfoV1Table.sIntegratedSysInfo.sExtDispConnInfo.sPath[0], Pcie, Gfx ); AGESA_STATUS_UPDATE (Status, AgesaStatus); } SystemInfoV1Table.sIntegratedSysInfo.usExtDispConnInfoOffset = offsetof (ATOM_INTEGRATED_SYSTEM_INFO_V6, sExtDispConnInfo); // Build PP table PpTable = (ATOM_PPLIB_POWERPLAYTABLE3*) &SystemInfoV1Table.ulPowerplayTable; // Build PP table Status = GfxPowerPlayBuildTable (PpTable, Gfx); AGESA_STATUS_UPDATE (Status, AgesaStatus); // Build info from fuses PpFuseArray = GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, GnbLibGetHeader (Gfx)); ASSERT (PpFuseArray != NULL); if (PpFuseArray != NULL) { // Build Display clock info GfxIntegratedInfoInitDispclkTable (PpFuseArray, &SystemInfoV1Table.sIntegratedSysInfo, Gfx); // Build Sclk info table GfxIntegratedInfoInitSclkTable (PpFuseArray, &SystemInfoV1Table.sIntegratedSysInfo, Gfx); } else { Status = AGESA_ERROR; AGESA_STATUS_UPDATE (Status, AgesaStatus); } // Fill in HTC Data GfxFillHtcData (&SystemInfoV1Table.sIntegratedSysInfo, Gfx); // Fill in NB P states VID GfxFillNbPStateVid (&SystemInfoV1Table.sIntegratedSysInfo, Gfx); // Fill in NCLK info GfxFillNclkInfo (&SystemInfoV1Table.sIntegratedSysInfo, Gfx); // Fill in the M3 arbitration control tables GfxFillM3ArbritrationControl (&SystemInfoV1Table.sIntegratedSysInfo, Gfx); // Fill South bridge MMIO Base address GfxFillSbMmioBaseAddress (&SystemInfoV1Table.sIntegratedSysInfo, Gfx); // Family specific data update GfxFmIntegratedInfoTableInit (&SystemInfoV1Table.sIntegratedSysInfo, Gfx); IDS_OPTION_CALLOUT (IDS_CALLOUT_GNB_INTEGRATED_TABLE_CONFIG, &SystemInfoV1Table.sIntegratedSysInfo, GnbLibGetHeader (Gfx)); //Copy integrated info table to Frame Buffer. (Do not use LibAmdMemCopy, routine not guaranteed access to above 4G memory in 32 bit mode.) IntegratedInfoAddress = (UINT32) (Gfx->UmaInfo.UmaSize - sizeof (ATOM_FUSION_SYSTEM_INFO_V1)); GfxLibCopyMemToFb ((VOID *) (&SystemInfoV1Table), IntegratedInfoAddress, sizeof (ATOM_FUSION_SYSTEM_INFO_V1), Gfx); IDS_HDT_CONSOLE (GNB_TRACE, "GfxIntegratedInfoTableInit Exit [0x%x]\n", Status); return Status; }