coreboot/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Family/0x14/F14NbLclkDpm.c

349 lines
12 KiB
C

/* $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],
ARRAY_SIZE(LclkDpmCacTable),
TRUE,
StdHeader
);
// Program activity threshold
IDS_HDT_CONSOLE (GNB_TRACE, "ActivityThreshold[4] - 0x%lx ActivityThreshold[5] - 0x%lx ActivityThreshold[6] - 0x%lx ActivityThreshold[7] - 0x%lx\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 < ARRAY_SIZE(SamplingPeriod); 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;
}