| /* $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%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 < (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; |
| } |
| |