summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Feature/NbFuseTable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Feature/NbFuseTable.c')
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Feature/NbFuseTable.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Feature/NbFuseTable.c b/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Feature/NbFuseTable.c
new file mode 100644
index 0000000000..d3f3e6c496
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/GNB/Nb/Feature/NbFuseTable.c
@@ -0,0 +1,401 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Fuse table initialization
+ *
+ *
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: GNB
+ * @e \$Revision: 39275 $ @e \$Date: 2010-10-09 08:22:05 +0800 (Sat, 09 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 GNB_MODULE_DEFINITIONS (GnbCommonLib)
+#include "GnbRegistersON.h"
+#include "NbSmuLib.h"
+#include "NbConfigData.h"
+#include "NbFuseTable.h"
+#include "NbFamilyServices.h"
+#include "GfxLib.h"
+#include "Filecode.h"
+
+#define FILECODE PROC_GNB_NB_FEATURE_NBFUSETABLE_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * 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
+ *----------------------------------------------------------------------------------------
+ */
+
+VOID
+NbFuseLoadDefaultFuseTable (
+ OUT PP_FUSE_ARRAY *PpFuseArray,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+VOID
+NbFuseLoadFuseTableFromFcr (
+ OUT PP_FUSE_ARRAY *PpFuseArray,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+VOID
+NbFuseDebugDump (
+ IN PP_FUSE_ARRAY *PpFuseArray,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+VOID
+NbFuseAdjustFuseTableToCurrentMainPllVco (
+ IN OUT PP_FUSE_ARRAY *PpFuseArray,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+PP_FUSE_ARRAY DefaultPpFuseArray = {
+ 0, ///< PP table revision
+ {1, 0, 0, 0, 0, 0}, ///< Valid DPM states
+ {0x40, 0, 0, 0, 0}, ///< Sclk DPM DID
+ {0, 0, 0, 0, 0}, ///< Sclk DPM VID
+ {0, 0, 0, 0, 0}, ///< Sclk DPM Cac
+ {1, 0, 0, 0, 0, 0}, ///< State policy flags
+ {2, 0, 0, 0, 0, 0}, ///< State policy label
+ {0x40, 0, 0, 0}, ///< VCLK DID
+ {0x40, 0, 0, 0}, ///< DCLK DID
+ 0, ///< Thermal SCLK
+ {0, 0, 0, 0, 0, 0}, ///< Vclk/Dclk selector
+ {0, 0, 0, 0}, ///< Valid Lclk DPM states
+ {0, 0, 0, 0}, ///< Lclk DPM DID
+ {0, 0, 0, 0}, ///< Lclk DPM VID
+ {0, 0, 0, 0}, ///< Displclk DID
+ 3, ///< Pcie Gen 2 VID
+ 0x10 ///< Main PLL id for 3200 VCO
+};
+
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Fuse Table Init
+ *
+ *
+ *
+ * @param[in] StdHeader Pointer to Standard configuration
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+NbFuseTableFeature (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ PP_FUSE_ARRAY *PpFuseArray;
+ D18F3xA0_STRUCT D18F3xA0;
+ BOOLEAN LoadDefaultFuses;
+ IDS_HDT_CONSOLE (GNB_TRACE, "NbFuseTableFeature Enter\n");
+
+ PpFuseArray = (PP_FUSE_ARRAY *) GnbAllocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, sizeof (PP_FUSE_ARRAY), StdHeader);
+ ASSERT (PpFuseArray != NULL);
+ if (PpFuseArray == NULL) {
+ IDS_HDT_CONSOLE (GNB_TRACE, " ERROR!!! Heap Allocation\n");
+ return AGESA_ERROR;
+ }
+ LibAmdMemFill (PpFuseArray, 0x00, sizeof (PP_FUSE_ARRAY), StdHeader);
+ GnbLibPciRead (
+ MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3xA0_ADDRESS),
+ AccessWidth32,
+ &D18F3xA0.Value,
+ StdHeader
+ );
+
+#ifndef GNB_FORCE_DEFAULT_FUSE
+ LoadDefaultFuses = FALSE;
+ if (D18F3xA0.Field.CofVidProg == 1) {
+ IDS_HDT_CONSOLE (NB_MISC, " Processor Fused\n");
+ NbFuseLoadFuseTableFromFcr (PpFuseArray, StdHeader);
+ if (PpFuseArray->PPlayTableRev == 0) {
+ IDS_HDT_CONSOLE (NB_MISC, " PowerPlay Table Unfused\n");
+ LoadDefaultFuses = TRUE;
+ }
+ } else {
+ IDS_HDT_CONSOLE (NB_MISC, " Processor Unfuse\n");
+ LoadDefaultFuses = TRUE;
+ }
+#else
+ LoadDefaultFuses = TRUE;
+#endif
+ if (LoadDefaultFuses) {
+ IDS_HDT_CONSOLE (NB_MISC, " Load default fuses\n");
+ NbFuseLoadDefaultFuseTable (PpFuseArray, StdHeader);
+ }
+ NbFmFuseAdjustFuseTablePatch (PpFuseArray, StdHeader);
+ NbFuseAdjustFuseTableToCurrentMainPllVco (PpFuseArray, StdHeader);
+ IDS_OPTION_CALLOUT (IDS_CALLOUT_GNB_PPFUSE_OVERRIDE, PpFuseArray, StdHeader);
+ GNB_DEBUG_CODE (
+ NbFuseDebugDump (PpFuseArray, StdHeader)
+ );
+ IDS_HDT_CONSOLE (GNB_TRACE, "NbFuseTableFeature Exit\n");
+ return AGESA_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Load Fuse Table From FCRs
+ *
+ *
+ * @param[out] PpFuseArray Pointer to save fuse table
+ * @param[in] StdHeader Pointer to Standard configuration
+ * @retval AGESA_STATUS
+ */
+
+VOID
+NbFuseLoadFuseTableFromFcr (
+ OUT PP_FUSE_ARRAY *PpFuseArray,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ FUSE_TABLE *FuseTable;
+ UINTN RegisterIndex;
+ FuseTable = NbFmGetFuseTranslationTable ();
+ for (RegisterIndex = 0; RegisterIndex < FuseTable->FuseTableLength; RegisterIndex++ ) {
+ UINTN FieldIndex;
+ UINTN FuseRegisterTableLength;
+ UINT32 FuseValue;
+ FuseRegisterTableLength = FuseTable->FuseTable[RegisterIndex].FuseRegisterTableLength;
+ FuseValue = NbSmuReadEfuse (
+ FuseTable->FuseTable[RegisterIndex].Register,
+ StdHeader
+ );
+ for (FieldIndex = 0; FieldIndex < FuseRegisterTableLength; FieldIndex++) {
+ FUSE_REGISTER_ENTRY RegisterEntry;
+ RegisterEntry = FuseTable->FuseTable[RegisterIndex].FuseRegisterTable[FieldIndex];
+ *((UINT8 *) PpFuseArray + RegisterEntry.FuseOffset) = (UINT8) ((FuseValue >> RegisterEntry.FieldOffset) &
+ ((1 << RegisterEntry.FieldWidth) - 1));
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Load Default Fuse Table
+ *
+ *
+ * @param[out] PpFuseArray Pointer to save fuse table
+ * @param[in] StdHeader Pointer to Standard configuration
+ * @retval AGESA_STATUS
+ */
+
+VOID
+NbFuseLoadDefaultFuseTable (
+ OUT PP_FUSE_ARRAY *PpFuseArray,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ D18F3x15C_STRUCT D18F3x15C;
+ UINT8 MaxVidIndex;
+ LibAmdMemCopy (PpFuseArray, &DefaultPpFuseArray, sizeof (PP_FUSE_ARRAY), StdHeader);
+ GnbLibPciRead (
+ MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS),
+ AccessWidth32,
+ &D18F3x15C.Value,
+ StdHeader
+ );
+ if (D18F3x15C.Value == 0) {
+ D18F3x15C.Value = 0x24242424;
+ GnbLibPciWrite (
+ MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS),
+ AccessWidth32,
+ &D18F3x15C.Value,
+ StdHeader
+ );
+ }
+ MaxVidIndex = GfxLibMaxVidIndex (StdHeader);
+ PpFuseArray->SclkDpmVid[0] = MaxVidIndex;
+ PpFuseArray->PcieGen2Vid = MaxVidIndex;
+
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Adjust DIDs to current main PLL VCO
+ *
+ * Main PLL VCO can be changed for debug perpouses
+ *
+ * @param[in,out] PpFuseArray Pointer to save fuse table
+ * @param[in] StdHeader Pointer to Standard configuration
+ */
+
+VOID
+NbFuseAdjustFuseTableToCurrentMainPllVco (
+ IN OUT PP_FUSE_ARRAY *PpFuseArray,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 EffectiveMainPllFreq10KHz;
+ UINT32 FusedMainPllFreq10KHz;
+ UINT32 TempVco;
+ UINTN Index;
+ EffectiveMainPllFreq10KHz = GfxLibGetMainPllFreq (StdHeader) * 100;
+ FusedMainPllFreq10KHz = (PpFuseArray->MainPllId + 0x10) * 100 * 100;
+ if (FusedMainPllFreq10KHz != EffectiveMainPllFreq10KHz) {
+ IDS_HDT_CONSOLE (NB_MISC, " WARNING! Adjusting fuse table for reprogrammed VCO\n");
+ for (Index = 0; Index < 5; Index++) {
+ if (PpFuseArray->SclkDpmDid[Index] != 0) {
+ TempVco = GfxLibCalculateClk (PpFuseArray->SclkDpmDid[Index], FusedMainPllFreq10KHz);
+ PpFuseArray->SclkDpmDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
+ }
+ }
+ for (Index = 0; Index < 4; Index++) {
+ if (PpFuseArray->VclkDid[Index] != 0) {
+ TempVco = GfxLibCalculateClk (PpFuseArray->VclkDid[Index], FusedMainPllFreq10KHz);
+ PpFuseArray->VclkDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
+ }
+ if (PpFuseArray->DclkDid[Index] != 0) {
+ TempVco = GfxLibCalculateClk (PpFuseArray->DclkDid[Index], FusedMainPllFreq10KHz);
+ PpFuseArray->DclkDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
+ }
+ if (PpFuseArray->LclkDpmDid[Index] != 0) {
+ TempVco = GfxLibCalculateClk (PpFuseArray->LclkDpmDid[Index], FusedMainPllFreq10KHz);
+ PpFuseArray->LclkDpmDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
+ }
+ if (PpFuseArray->DisplclkDid[Index] != 0) {
+ TempVco = GfxLibCalculateClk (PpFuseArray->DisplclkDid[Index], FusedMainPllFreq10KHz);
+ PpFuseArray->DisplclkDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
+ }
+ }
+ if (PpFuseArray->SclkThermDid != 0) {
+ TempVco = GfxLibCalculateClk (PpFuseArray->SclkThermDid , FusedMainPllFreq10KHz);
+ PpFuseArray->SclkThermDid = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Debug dump fuse table
+ *
+ *
+ * @param[out] PpFuseArray Pointer to save fuse table
+ * @param[in] StdHeader Pointer to Standard configuration
+ */
+
+VOID
+NbFuseDebugDump (
+ IN PP_FUSE_ARRAY *PpFuseArray,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINTN Index;
+ UINT32 EffectiveMainPllFreq10KHz;
+
+ EffectiveMainPllFreq10KHz = GfxLibGetMainPllFreq (StdHeader) * 100;
+ IDS_HDT_CONSOLE (NB_MISC, "<------------ GNB FUSE TABLE------------>\n");
+ for (Index = 0; Index < 4; Index++) {
+ if (PpFuseArray->LclkDpmValid[Index] != 0) {
+ IDS_HDT_CONSOLE (
+ NB_MISC,
+ " LCLK DID[%d] - 0x%02x (%dMHz)\n",
+ Index,
+ PpFuseArray->LclkDpmDid[Index],
+ GfxLibCalculateClk (PpFuseArray->LclkDpmDid[Index], EffectiveMainPllFreq10KHz) / 100);
+ IDS_HDT_CONSOLE (NB_MISC, " LCLK VID[%d] - 0x02%x\n", Index, PpFuseArray->LclkDpmVid[Index]);
+ }
+ }
+ for (Index = 0; Index < 4; Index++) {
+ IDS_HDT_CONSOLE (
+ NB_MISC,
+ " VCLK DID[%d] - 0x%02x (%dMHz)\n",
+ Index,
+ PpFuseArray->VclkDid[Index],
+ (PpFuseArray->VclkDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->VclkDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
+ );
+ IDS_HDT_CONSOLE (
+ NB_MISC,
+ " DCLK DID[%d] - 0x%02x (%dMHz)\n",
+ Index,
+ PpFuseArray->DclkDid[Index],
+ (PpFuseArray->DclkDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->DclkDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
+ );
+ }
+ for (Index = 0; Index < 4; Index++) {
+ IDS_HDT_CONSOLE (
+ NB_MISC,
+ " DISPCLK DID[%d] - 0x%02x (%dMHz)\n",
+ Index,
+ PpFuseArray->DisplclkDid[Index],
+ (PpFuseArray->DisplclkDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->DisplclkDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
+ );
+ }
+ for (Index = 0; Index < 5; Index++) {
+ IDS_HDT_CONSOLE (
+ NB_MISC,
+ " SCLK DID[%d] - 0x%02x (%dMHz)\n",
+ Index,
+ PpFuseArray->SclkDpmDid[Index],
+ (PpFuseArray->SclkDpmDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->SclkDpmDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
+ );
+ IDS_HDT_CONSOLE (NB_MISC, " SCLK VID[%d] - 0x%02x\n", Index, PpFuseArray->SclkDpmVid[Index]);
+ }
+ for (Index = 0; Index < 6; Index++) {
+ IDS_HDT_CONSOLE (NB_MISC, " State #%d\n", Index);
+ IDS_HDT_CONSOLE (NB_MISC, " Policy Label - 0x%x\n", PpFuseArray->PolicyLabel[Index]);
+ IDS_HDT_CONSOLE (NB_MISC, " Policy Flag - 0x%x\n", PpFuseArray->PolicyFlags[Index]);
+ IDS_HDT_CONSOLE (NB_MISC, " Valid SCLK - 0x%x\n", PpFuseArray->SclkDpmValid[Index]);
+ IDS_HDT_CONSOLE (NB_MISC, " Vclk/Dclk Index - 0x%x\n", PpFuseArray->VclkDclkSel[Index]);
+ }
+ IDS_HDT_CONSOLE (NB_MISC, " GEN2 VID - 0x%x\n", PpFuseArray->PcieGen2Vid);
+ IDS_HDT_CONSOLE (NB_MISC, " Main PLL Id - 0x%x\n", PpFuseArray->MainPllId);
+ IDS_HDT_CONSOLE (NB_MISC, "<------------ GNB FUSE END-------------->\n");
+}