5 * Fuse table initialization
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 48498 $ @e \$Date: 2011-03-09 12:44:53 -0700 (Wed, 09 Mar 2011) $
16 *****************************************************************************
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 * ***************************************************************************
47 /*----------------------------------------------------------------------------------------
48 * M O D U L E S U S E D
49 *----------------------------------------------------------------------------------------
55 #include "heapManager.h"
57 #include "GnbFuseTable.h"
58 #include GNB_MODULE_DEFINITIONS (GnbCommonLib)
59 #include "GnbRegistersON.h"
61 #include "NbConfigData.h"
62 #include "NbFuseTable.h"
63 #include "NbFamilyServices.h"
67 #define FILECODE PROC_GNB_NB_FEATURE_NBFUSETABLE_FILECODE
68 /*----------------------------------------------------------------------------------------
69 * D E F I N I T I O N S A N D M A C R O S
70 *----------------------------------------------------------------------------------------
73 /*----------------------------------------------------------------------------------------
74 * T Y P E D E F S A N D S T R U C T U R E S
75 *----------------------------------------------------------------------------------------
78 /*----------------------------------------------------------------------------------------
79 * 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
80 *----------------------------------------------------------------------------------------
84 NbFuseLoadDefaultFuseTable (
85 OUT PP_FUSE_ARRAY *PpFuseArray,
86 IN AMD_CONFIG_PARAMS *StdHeader
90 NbFuseLoadFuseTableFromFcr (
91 OUT PP_FUSE_ARRAY *PpFuseArray,
92 IN AMD_CONFIG_PARAMS *StdHeader
97 IN PP_FUSE_ARRAY *PpFuseArray,
98 IN AMD_CONFIG_PARAMS *StdHeader
102 NbFuseAdjustFuseTableToCurrentMainPllVco (
103 IN OUT PP_FUSE_ARRAY *PpFuseArray,
104 IN AMD_CONFIG_PARAMS *StdHeader
107 PP_FUSE_ARRAY DefaultPpFuseArray = {
108 0, ///< PP table revision
109 {1, 0, 0, 0, 0, 0}, ///< Valid DPM states
110 {0x40, 0, 0, 0, 0}, ///< Sclk DPM DID
111 {0, 0, 0, 0, 0}, ///< Sclk DPM VID
112 {0, 0, 0, 0, 0}, ///< Sclk DPM Cac
113 {1, 0, 0, 0, 0, 0}, ///< State policy flags
114 {2, 0, 0, 0, 0, 0}, ///< State policy label
115 {0x40, 0, 0, 0}, ///< VCLK DID
116 {0x40, 0, 0, 0}, ///< DCLK DID
118 {0, 0, 0, 0, 0, 0}, ///< Vclk/Dclk selector
119 {0, 0, 0, 0}, ///< Valid Lclk DPM states
120 {0, 0, 0, 0}, ///< Lclk DPM DID
121 {0, 0, 0, 0}, ///< Lclk DPM VID
122 {0, 0, 0, 0}, ///< Displclk DID
123 3, ///< Pcie Gen 2 VID
124 0x10 ///< Main PLL id for 3200 VCO
128 /*----------------------------------------------------------------------------------------*/
134 * @param[in] StdHeader Pointer to Standard configuration
135 * @retval AGESA_STATUS
140 IN AMD_CONFIG_PARAMS *StdHeader
143 PP_FUSE_ARRAY *PpFuseArray;
144 D18F3xA0_STRUCT D18F3xA0;
145 BOOLEAN LoadDefaultFuses;
146 IDS_HDT_CONSOLE (GNB_TRACE, "NbFuseTableFeature Enter\n");
148 PpFuseArray = (PP_FUSE_ARRAY *) GnbAllocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, sizeof (PP_FUSE_ARRAY), StdHeader);
149 ASSERT (PpFuseArray != NULL);
150 if (PpFuseArray == NULL) {
151 IDS_HDT_CONSOLE (GNB_TRACE, " ERROR!!! Heap Allocation\n");
154 LibAmdMemFill (PpFuseArray, 0x00, sizeof (PP_FUSE_ARRAY), StdHeader);
156 MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3xA0_ADDRESS),
162 #ifndef GNB_FORCE_DEFAULT_FUSE
163 LoadDefaultFuses = FALSE;
164 if (D18F3xA0.Field.CofVidProg == 1) {
165 IDS_HDT_CONSOLE (NB_MISC, " Processor Fused\n");
166 NbFuseLoadFuseTableFromFcr (PpFuseArray, StdHeader);
167 if (PpFuseArray->PPlayTableRev == 0) {
168 IDS_HDT_CONSOLE (NB_MISC, " PowerPlay Table Unfused\n");
169 LoadDefaultFuses = TRUE;
172 IDS_HDT_CONSOLE (NB_MISC, " Processor Unfuse\n");
173 LoadDefaultFuses = TRUE;
176 LoadDefaultFuses = TRUE;
178 if (LoadDefaultFuses) {
179 IDS_HDT_CONSOLE (NB_MISC, " Load default fuses\n");
180 NbFuseLoadDefaultFuseTable (PpFuseArray, StdHeader);
182 NbFmFuseAdjustFuseTablePatch (PpFuseArray, StdHeader);
183 NbFuseAdjustFuseTableToCurrentMainPllVco (PpFuseArray, StdHeader);
184 IDS_OPTION_CALLOUT (IDS_CALLOUT_GNB_PPFUSE_OVERRIDE, PpFuseArray, StdHeader);
186 NbFuseDebugDump (PpFuseArray, StdHeader)
188 IDS_HDT_CONSOLE (GNB_TRACE, "NbFuseTableFeature Exit\n");
189 return AGESA_SUCCESS;
193 /*----------------------------------------------------------------------------------------*/
195 * Load Fuse Table From FCRs
198 * @param[out] PpFuseArray Pointer to save fuse table
199 * @param[in] StdHeader Pointer to Standard configuration
200 * @retval AGESA_STATUS
204 NbFuseLoadFuseTableFromFcr (
205 OUT PP_FUSE_ARRAY *PpFuseArray,
206 IN AMD_CONFIG_PARAMS *StdHeader
209 FUSE_TABLE *FuseTable;
211 FuseTable = NbFmGetFuseTranslationTable ();
212 for (RegisterIndex = 0; RegisterIndex < FuseTable->FuseTableLength; RegisterIndex++ ) {
214 UINTN FuseRegisterTableLength;
216 FuseRegisterTableLength = FuseTable->FuseTable[RegisterIndex].FuseRegisterTableLength;
217 FuseValue = NbSmuReadEfuse (
218 FuseTable->FuseTable[RegisterIndex].Register,
221 for (FieldIndex = 0; FieldIndex < FuseRegisterTableLength; FieldIndex++) {
222 FUSE_REGISTER_ENTRY RegisterEntry;
224 UINT32 FuseArrauValue;
225 RegisterEntry = FuseTable->FuseTable[RegisterIndex].FuseRegisterTable[FieldIndex];
226 FuseArrayPtr = (UINT8*) PpFuseArray + RegisterEntry.FuseOffset;
227 FuseArrauValue = (FuseValue >> RegisterEntry.FieldOffset) & ((1 << RegisterEntry.FieldWidth) - 1);
228 if (RegisterEntry.FieldWidth > 16) {
229 *((UINT32 *) FuseArrayPtr) = FuseArrauValue;
230 } else if (RegisterEntry.FieldWidth > 8) {
231 *((UINT16 *) FuseArrayPtr) = (UINT16) FuseArrauValue;
233 *((UINT8 *) FuseArrayPtr) = (UINT8) FuseArrauValue;
239 /*----------------------------------------------------------------------------------------*/
241 * Load Default Fuse Table
244 * @param[out] PpFuseArray Pointer to save fuse table
245 * @param[in] StdHeader Pointer to Standard configuration
246 * @retval AGESA_STATUS
250 NbFuseLoadDefaultFuseTable (
251 OUT PP_FUSE_ARRAY *PpFuseArray,
252 IN AMD_CONFIG_PARAMS *StdHeader
255 D18F3x15C_STRUCT D18F3x15C;
257 LibAmdMemCopy (PpFuseArray, &DefaultPpFuseArray, sizeof (PP_FUSE_ARRAY), StdHeader);
259 MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS),
264 if (D18F3x15C.Value == 0) {
265 D18F3x15C.Value = 0x24242424;
267 MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS),
273 MaxVidIndex = GfxLibMaxVidIndex (StdHeader);
274 PpFuseArray->SclkDpmVid[0] = MaxVidIndex;
275 PpFuseArray->PcieGen2Vid = MaxVidIndex;
279 /*----------------------------------------------------------------------------------------*/
281 * Adjust DIDs to current main PLL VCO
283 * Main PLL VCO can be changed for debug perpouses
285 * @param[in,out] PpFuseArray Pointer to save fuse table
286 * @param[in] StdHeader Pointer to Standard configuration
290 NbFuseAdjustFuseTableToCurrentMainPllVco (
291 IN OUT PP_FUSE_ARRAY *PpFuseArray,
292 IN AMD_CONFIG_PARAMS *StdHeader
295 UINT32 EffectiveMainPllFreq10KHz;
296 UINT32 FusedMainPllFreq10KHz;
299 EffectiveMainPllFreq10KHz = GfxLibGetMainPllFreq (StdHeader) * 100;
300 FusedMainPllFreq10KHz = (PpFuseArray->MainPllId + 0x10) * 100 * 100;
301 if (FusedMainPllFreq10KHz != EffectiveMainPllFreq10KHz) {
302 IDS_HDT_CONSOLE (NB_MISC, " WARNING! Adjusting fuse table for reprogrammed VCO\n");
303 IDS_HDT_CONSOLE (NB_MISC, " Actual main Freq %d \n", EffectiveMainPllFreq10KHz);
304 IDS_HDT_CONSOLE (NB_MISC, " Fused main Freq %d \n", FusedMainPllFreq10KHz);
305 for (Index = 0; Index < 5; Index++) {
306 if (PpFuseArray->SclkDpmDid[Index] != 0) {
307 TempVco = GfxLibCalculateClk (PpFuseArray->SclkDpmDid[Index], FusedMainPllFreq10KHz);
308 PpFuseArray->SclkDpmDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
311 for (Index = 0; Index < 4; Index++) {
312 if (PpFuseArray->VclkDid[Index] != 0) {
313 TempVco = GfxLibCalculateClk (PpFuseArray->VclkDid[Index], FusedMainPllFreq10KHz);
314 PpFuseArray->VclkDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
316 if (PpFuseArray->DclkDid[Index] != 0) {
317 TempVco = GfxLibCalculateClk (PpFuseArray->DclkDid[Index], FusedMainPllFreq10KHz);
318 PpFuseArray->DclkDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
320 if (PpFuseArray->LclkDpmDid[Index] != 0) {
321 TempVco = GfxLibCalculateClk (PpFuseArray->LclkDpmDid[Index], FusedMainPllFreq10KHz);
322 PpFuseArray->LclkDpmDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
324 if (PpFuseArray->DisplclkDid[Index] != 0) {
325 TempVco = GfxLibCalculateClk (PpFuseArray->DisplclkDid[Index], FusedMainPllFreq10KHz);
326 PpFuseArray->DisplclkDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
329 if (PpFuseArray->SclkThermDid != 0) {
330 TempVco = GfxLibCalculateClk (PpFuseArray->SclkThermDid , FusedMainPllFreq10KHz);
331 PpFuseArray->SclkThermDid = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
336 /*----------------------------------------------------------------------------------------*/
338 * Debug dump fuse table
341 * @param[out] PpFuseArray Pointer to save fuse table
342 * @param[in] StdHeader Pointer to Standard configuration
347 IN PP_FUSE_ARRAY *PpFuseArray,
348 IN AMD_CONFIG_PARAMS *StdHeader
352 UINT32 EffectiveMainPllFreq10KHz;
354 EffectiveMainPllFreq10KHz = GfxLibGetMainPllFreq (StdHeader) * 100;
355 IDS_HDT_CONSOLE (NB_MISC, "<------------ GNB FUSE TABLE------------>\n");
356 for (Index = 0; Index < 4; Index++) {
357 if (PpFuseArray->LclkDpmValid[Index] != 0) {
360 " LCLK DID[%d] - 0x%02x (%dMHz)\n",
362 PpFuseArray->LclkDpmDid[Index],
363 GfxLibCalculateClk (PpFuseArray->LclkDpmDid[Index], EffectiveMainPllFreq10KHz) / 100);
364 IDS_HDT_CONSOLE (NB_MISC, " LCLK VID[%d] - 0x02%x\n", Index, PpFuseArray->LclkDpmVid[Index]);
367 for (Index = 0; Index < 4; Index++) {
370 " VCLK DID[%d] - 0x%02x (%dMHz)\n",
372 PpFuseArray->VclkDid[Index],
373 (PpFuseArray->VclkDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->VclkDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
377 " DCLK DID[%d] - 0x%02x (%dMHz)\n",
379 PpFuseArray->DclkDid[Index],
380 (PpFuseArray->DclkDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->DclkDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
383 for (Index = 0; Index < 4; Index++) {
386 " DISPCLK DID[%d] - 0x%02x (%dMHz)\n",
388 PpFuseArray->DisplclkDid[Index],
389 (PpFuseArray->DisplclkDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->DisplclkDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
392 for (Index = 0; Index < 6; Index++) {
395 " SCLK DID[%d] - 0x%02x (%dMHz)\n",
397 PpFuseArray->SclkDpmDid[Index],
398 (PpFuseArray->SclkDpmDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->SclkDpmDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
402 " SCLK TDP[%d] - 0x%x \n",
404 PpFuseArray->SclkDpmTdpLimit[Index]
406 IDS_HDT_CONSOLE (NB_MISC, " SCLK VID[%d] - 0x%02x\n", Index, PpFuseArray->SclkDpmVid[Index]);
408 for (Index = 0; Index < 6; Index++) {
409 IDS_HDT_CONSOLE (NB_MISC, " State #%d\n", Index);
410 IDS_HDT_CONSOLE (NB_MISC, " Policy Label - 0x%x\n", PpFuseArray->PolicyLabel[Index]);
411 IDS_HDT_CONSOLE (NB_MISC, " Policy Flag - 0x%x\n", PpFuseArray->PolicyFlags[Index]);
412 IDS_HDT_CONSOLE (NB_MISC, " Valid SCLK - 0x%x\n", PpFuseArray->SclkDpmValid[Index]);
413 IDS_HDT_CONSOLE (NB_MISC, " Vclk/Dclk Index - 0x%x\n", PpFuseArray->VclkDclkSel[Index]);
415 IDS_HDT_CONSOLE (NB_MISC, " GEN2 VID - 0x%x\n", PpFuseArray->PcieGen2Vid);
416 IDS_HDT_CONSOLE (NB_MISC, " Main PLL Id - 0x%x\n", PpFuseArray->MainPllId);
417 IDS_HDT_CONSOLE (NB_MISC, " GpuBoostCap - %x\n", PpFuseArray->GpuBoostCap);
418 IDS_HDT_CONSOLE (NB_MISC, " SclkDpmBoostMargin - %x\n", PpFuseArray->SclkDpmBoostMargin);
419 IDS_HDT_CONSOLE (NB_MISC, " SclkDpmThrottleMargin - %x\n", PpFuseArray->SclkDpmThrottleMargin);
420 IDS_HDT_CONSOLE (NB_MISC, " SclkDpmTdpLimitPG - %x\n", PpFuseArray->SclkDpmTdpLimitPG);
422 NB_MISC, " SclkThermDid - %x(%dMHz)\n",
423 PpFuseArray->SclkThermDid,
424 (PpFuseArray->SclkThermDid != 0) ? (GfxLibCalculateClk (PpFuseArray->SclkThermDid, EffectiveMainPllFreq10KHz) / 100) : 0
426 IDS_HDT_CONSOLE (NB_MISC, "<------------ GNB FUSE END-------------->\n");