summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Family/0x14/F14NbLclkDpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Family/0x14/F14NbLclkDpm.c')
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Family/0x14/F14NbLclkDpm.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Family/0x14/F14NbLclkDpm.c b/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Family/0x14/F14NbLclkDpm.c
new file mode 100644
index 0000000000..3c918aa2cb
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Family/0x14/F14NbLclkDpm.c
@@ -0,0 +1,348 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * LCLK DPM initialization
+ *
+ *
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: GNB
+ * @e \$Revision: 39007 $ @e \$Date: 2010-10-05 00:32:54 +0800 (Tue, 05 Oct 2010) $
+ *
+ */
+/*
+ *****************************************************************************
+ *
+ * Copyright (c) 2011, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "heapManager.h"
+#include "Gnb.h"
+#include "GnbFuseTable.h"
+#include "GnbPcie.h"
+#include GNB_MODULE_DEFINITIONS (GnbCommonLib)
+#include GNB_MODULE_DEFINITIONS (GnbPcieConfig)
+#include "GnbRegistersON.h"
+#include "OptionGnb.h"
+#include "GfxLib.h"
+#include "NbConfigData.h"
+#include "NbSmuLib.h"
+#include "NbLclkDpm.h"
+#include "NbFamilyServices.h"
+#include "Filecode.h"
+
+#define FILECODE PROC_GNB_NB_FAMILY_0X14_F14NBLCLKDPM_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+extern GNB_BUILD_OPTIONS GnbBuildOptions;
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+UINT32 LclkDpmCacTable [] = {
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0
+};
+
+UINT32 LclkDpmActivityThresholdTable [] = {
+ 0x100,
+ 0x40FFFF,
+ 0x40FFFF,
+ 0x0
+};
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Init NB LCLK DPM in Root Complex Activity mode
+ *
+ *
+ *
+ * @param[in] StdHeader Pointer to Standard configuration
+ * @retval Initialization status
+ */
+
+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;
+}
+
+
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Family specific check PsppPolicy to initially enable appropriate DPM states
+ *
+ *
+ * @param[in] LclkDpmValid UINT32 Lclk Dpm Valid
+ * @param[in] StdHeader Pointer to AMD_CONFIG_PARAMS
+ */
+UINT32
+NbFmDpmStateBootupInit (
+ IN UINT32 LclkDpmValid,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ PCIe_PLATFORM_CONFIG *Pcie;
+ UINT32 LclkDpmValidState;
+ UINT8 Dpm0ValidOffset;
+
+ if ((LclkDpmValid & 0xFF) == 0) {
+ IDS_HDT_CONSOLE (NB_MISC, " No valid DPM State Bootup Init\n");
+ return 0;
+ }
+
+ // For ON, from DPM0(the most right non-zero bit) to highest DPM(bit 7)
+ Dpm0ValidOffset = LibAmdBitScanForward (LclkDpmValid & 0xFF);
+ // Enable DPM0
+ LclkDpmValidState = 1 << Dpm0ValidOffset;
+
+ if (PcieLocateConfigurationData (StdHeader, &Pcie) == AGESA_SUCCESS) {
+ switch (Pcie->PsppPolicy) {
+ case PsppDisabled:
+ case PsppPerformance:
+ case PsppBalanceHigh:
+ if ((Dpm0ValidOffset + 2) <= 7) {
+ // Enable DPM0 + DPM2
+ LclkDpmValidState = LclkDpmValidState + (1 << (Dpm0ValidOffset + 2));
+ }
+ break;
+ case PsppBalanceLow:
+ if ((Dpm0ValidOffset + 1) <= 7) {
+ // Enable DPM0 + DPM1
+ LclkDpmValidState = LclkDpmValidState + (1 << (Dpm0ValidOffset + 1));
+ }
+ break;
+ case PsppPowerSaving:
+ // Enable DPM0
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ } else {
+ IDS_HDT_CONSOLE (NB_MISC, " DPM State Bootup Init Pcie Locate ConfigurationData Fail!! -- Enable DPM0 only\n");
+ }
+ return LclkDpmValidState;
+}
+