blob: 0ae550789f148c9ffb64c9d3b2d70a76f9a3f33d [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * Fuse table initialization
6 *
7 *
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: GNB
efdesign9884cbce22011-08-04 12:09:17 -060012 * @e \$Revision: 48498 $ @e \$Date: 2011-03-09 12:44:53 -0700 (Wed, 09 Mar 2011) $
Frank Vibrans2b4c8312011-02-14 18:30:54 +000013 *
14 */
15/*
16 *****************************************************************************
17 *
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100020 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000021 * 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.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100028 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
Frank Vibrans2b4c8312011-02-14 18:30:54 +000030 * from this software without specific prior written permission.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100031 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000032 * 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.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100042 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000043 * ***************************************************************************
44 *
45 */
46
47/*----------------------------------------------------------------------------------------
48 * M O D U L E S U S E D
49 *----------------------------------------------------------------------------------------
50 */
51
52#include "AGESA.h"
53#include "amdlib.h"
54#include "Ids.h"
55#include "heapManager.h"
56#include "Gnb.h"
57#include "GnbFuseTable.h"
58#include GNB_MODULE_DEFINITIONS (GnbCommonLib)
59#include "GnbRegistersON.h"
60#include "NbSmuLib.h"
61#include "NbConfigData.h"
62#include "NbFuseTable.h"
63#include "NbFamilyServices.h"
64#include "GfxLib.h"
65#include "Filecode.h"
66
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 *----------------------------------------------------------------------------------------
71 */
72
73/*----------------------------------------------------------------------------------------
74 * T Y P E D E F S A N D S T R U C T U R E S
75 *----------------------------------------------------------------------------------------
76 */
77
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 *----------------------------------------------------------------------------------------
81 */
82
83VOID
84NbFuseLoadDefaultFuseTable (
85 OUT PP_FUSE_ARRAY *PpFuseArray,
86 IN AMD_CONFIG_PARAMS *StdHeader
87 );
88
89VOID
90NbFuseLoadFuseTableFromFcr (
91 OUT PP_FUSE_ARRAY *PpFuseArray,
92 IN AMD_CONFIG_PARAMS *StdHeader
93 );
94
95VOID
96NbFuseDebugDump (
97 IN PP_FUSE_ARRAY *PpFuseArray,
98 IN AMD_CONFIG_PARAMS *StdHeader
99 );
100
101VOID
102NbFuseAdjustFuseTableToCurrentMainPllVco (
103 IN OUT PP_FUSE_ARRAY *PpFuseArray,
104 IN AMD_CONFIG_PARAMS *StdHeader
105 );
106
107PP_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
117 0, ///< Thermal SCLK
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
125};
126
127
128/*----------------------------------------------------------------------------------------*/
129/**
130 * Fuse Table Init
131 *
132 *
133 *
134 * @param[in] StdHeader Pointer to Standard configuration
135 * @retval AGESA_STATUS
136 */
137
138AGESA_STATUS
139NbFuseTableFeature (
140 IN AMD_CONFIG_PARAMS *StdHeader
141 )
142{
143 PP_FUSE_ARRAY *PpFuseArray;
144 D18F3xA0_STRUCT D18F3xA0;
145 BOOLEAN LoadDefaultFuses;
146 IDS_HDT_CONSOLE (GNB_TRACE, "NbFuseTableFeature Enter\n");
147
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");
152 return AGESA_ERROR;
153 }
154 LibAmdMemFill (PpFuseArray, 0x00, sizeof (PP_FUSE_ARRAY), StdHeader);
155 GnbLibPciRead (
156 MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3xA0_ADDRESS),
157 AccessWidth32,
158 &D18F3xA0.Value,
159 StdHeader
160 );
161
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;
170 }
171 } else {
172 IDS_HDT_CONSOLE (NB_MISC, " Processor Unfuse\n");
173 LoadDefaultFuses = TRUE;
174 }
175#else
176 LoadDefaultFuses = TRUE;
177#endif
178 if (LoadDefaultFuses) {
179 IDS_HDT_CONSOLE (NB_MISC, " Load default fuses\n");
180 NbFuseLoadDefaultFuseTable (PpFuseArray, StdHeader);
181 }
182 NbFmFuseAdjustFuseTablePatch (PpFuseArray, StdHeader);
183 NbFuseAdjustFuseTableToCurrentMainPllVco (PpFuseArray, StdHeader);
184 IDS_OPTION_CALLOUT (IDS_CALLOUT_GNB_PPFUSE_OVERRIDE, PpFuseArray, StdHeader);
185 GNB_DEBUG_CODE (
186 NbFuseDebugDump (PpFuseArray, StdHeader)
187 );
188 IDS_HDT_CONSOLE (GNB_TRACE, "NbFuseTableFeature Exit\n");
189 return AGESA_SUCCESS;
190}
191
192
193/*----------------------------------------------------------------------------------------*/
194/**
195 * Load Fuse Table From FCRs
196 *
197 *
198 * @param[out] PpFuseArray Pointer to save fuse table
199 * @param[in] StdHeader Pointer to Standard configuration
200 * @retval AGESA_STATUS
201 */
202
203VOID
204NbFuseLoadFuseTableFromFcr (
205 OUT PP_FUSE_ARRAY *PpFuseArray,
206 IN AMD_CONFIG_PARAMS *StdHeader
207 )
208{
209 FUSE_TABLE *FuseTable;
210 UINTN RegisterIndex;
211 FuseTable = NbFmGetFuseTranslationTable ();
212 for (RegisterIndex = 0; RegisterIndex < FuseTable->FuseTableLength; RegisterIndex++ ) {
213 UINTN FieldIndex;
214 UINTN FuseRegisterTableLength;
215 UINT32 FuseValue;
216 FuseRegisterTableLength = FuseTable->FuseTable[RegisterIndex].FuseRegisterTableLength;
217 FuseValue = NbSmuReadEfuse (
218 FuseTable->FuseTable[RegisterIndex].Register,
219 StdHeader
220 );
221 for (FieldIndex = 0; FieldIndex < FuseRegisterTableLength; FieldIndex++) {
222 FUSE_REGISTER_ENTRY RegisterEntry;
efdesign9884cbce22011-08-04 12:09:17 -0600223 UINT8 *FuseArrayPtr;
224 UINT32 FuseArrauValue;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000225 RegisterEntry = FuseTable->FuseTable[RegisterIndex].FuseRegisterTable[FieldIndex];
efdesign9884cbce22011-08-04 12:09:17 -0600226 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;
232 } else {
233 *((UINT8 *) FuseArrayPtr) = (UINT8) FuseArrauValue;
234 }
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000235 }
236 }
237}
238
239/*----------------------------------------------------------------------------------------*/
240/**
241 * Load Default Fuse Table
242 *
243 *
244 * @param[out] PpFuseArray Pointer to save fuse table
245 * @param[in] StdHeader Pointer to Standard configuration
246 * @retval AGESA_STATUS
247 */
248
249VOID
250NbFuseLoadDefaultFuseTable (
251 OUT PP_FUSE_ARRAY *PpFuseArray,
252 IN AMD_CONFIG_PARAMS *StdHeader
253 )
254{
255 D18F3x15C_STRUCT D18F3x15C;
256 UINT8 MaxVidIndex;
257 LibAmdMemCopy (PpFuseArray, &DefaultPpFuseArray, sizeof (PP_FUSE_ARRAY), StdHeader);
258 GnbLibPciRead (
259 MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS),
260 AccessWidth32,
261 &D18F3x15C.Value,
262 StdHeader
263 );
264 if (D18F3x15C.Value == 0) {
265 D18F3x15C.Value = 0x24242424;
266 GnbLibPciWrite (
267 MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS),
268 AccessWidth32,
269 &D18F3x15C.Value,
270 StdHeader
271 );
272 }
273 MaxVidIndex = GfxLibMaxVidIndex (StdHeader);
274 PpFuseArray->SclkDpmVid[0] = MaxVidIndex;
275 PpFuseArray->PcieGen2Vid = MaxVidIndex;
276
277}
278
279/*----------------------------------------------------------------------------------------*/
280/**
281 * Adjust DIDs to current main PLL VCO
282 *
283 * Main PLL VCO can be changed for debug perpouses
284 *
285 * @param[in,out] PpFuseArray Pointer to save fuse table
286 * @param[in] StdHeader Pointer to Standard configuration
287 */
288
289VOID
290NbFuseAdjustFuseTableToCurrentMainPllVco (
291 IN OUT PP_FUSE_ARRAY *PpFuseArray,
292 IN AMD_CONFIG_PARAMS *StdHeader
293 )
294{
295 UINT32 EffectiveMainPllFreq10KHz;
296 UINT32 FusedMainPllFreq10KHz;
297 UINT32 TempVco;
298 UINTN Index;
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");
efdesign9884cbce22011-08-04 12:09:17 -0600303 IDS_HDT_CONSOLE (NB_MISC, " Actual main Freq %d \n", EffectiveMainPllFreq10KHz);
304 IDS_HDT_CONSOLE (NB_MISC, " Fused main Freq %d \n", FusedMainPllFreq10KHz);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000305 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);
309 }
310 }
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);
315 }
316 if (PpFuseArray->DclkDid[Index] != 0) {
317 TempVco = GfxLibCalculateClk (PpFuseArray->DclkDid[Index], FusedMainPllFreq10KHz);
318 PpFuseArray->DclkDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
319 }
320 if (PpFuseArray->LclkDpmDid[Index] != 0) {
321 TempVco = GfxLibCalculateClk (PpFuseArray->LclkDpmDid[Index], FusedMainPllFreq10KHz);
322 PpFuseArray->LclkDpmDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
323 }
324 if (PpFuseArray->DisplclkDid[Index] != 0) {
325 TempVco = GfxLibCalculateClk (PpFuseArray->DisplclkDid[Index], FusedMainPllFreq10KHz);
326 PpFuseArray->DisplclkDid[Index] = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
327 }
328 }
329 if (PpFuseArray->SclkThermDid != 0) {
330 TempVco = GfxLibCalculateClk (PpFuseArray->SclkThermDid , FusedMainPllFreq10KHz);
331 PpFuseArray->SclkThermDid = GfxLibCalculateDid (TempVco, EffectiveMainPllFreq10KHz);
332 }
333 }
334}
335
336/*----------------------------------------------------------------------------------------*/
337/**
338 * Debug dump fuse table
339 *
340 *
341 * @param[out] PpFuseArray Pointer to save fuse table
342 * @param[in] StdHeader Pointer to Standard configuration
343 */
344
345VOID
346NbFuseDebugDump (
347 IN PP_FUSE_ARRAY *PpFuseArray,
348 IN AMD_CONFIG_PARAMS *StdHeader
349 )
350{
351 UINTN Index;
352 UINT32 EffectiveMainPllFreq10KHz;
353
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) {
358 IDS_HDT_CONSOLE (
359 NB_MISC,
360 " LCLK DID[%d] - 0x%02x (%dMHz)\n",
361 Index,
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]);
365 }
366 }
367 for (Index = 0; Index < 4; Index++) {
368 IDS_HDT_CONSOLE (
369 NB_MISC,
370 " VCLK DID[%d] - 0x%02x (%dMHz)\n",
371 Index,
372 PpFuseArray->VclkDid[Index],
373 (PpFuseArray->VclkDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->VclkDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
374 );
375 IDS_HDT_CONSOLE (
376 NB_MISC,
377 " DCLK DID[%d] - 0x%02x (%dMHz)\n",
378 Index,
379 PpFuseArray->DclkDid[Index],
380 (PpFuseArray->DclkDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->DclkDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
381 );
382 }
383 for (Index = 0; Index < 4; Index++) {
384 IDS_HDT_CONSOLE (
385 NB_MISC,
386 " DISPCLK DID[%d] - 0x%02x (%dMHz)\n",
387 Index,
388 PpFuseArray->DisplclkDid[Index],
389 (PpFuseArray->DisplclkDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->DisplclkDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
390 );
391 }
efdesign9884cbce22011-08-04 12:09:17 -0600392 for (Index = 0; Index < 6; Index++) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000393 IDS_HDT_CONSOLE (
394 NB_MISC,
395 " SCLK DID[%d] - 0x%02x (%dMHz)\n",
396 Index,
397 PpFuseArray->SclkDpmDid[Index],
398 (PpFuseArray->SclkDpmDid[Index] != 0) ? (GfxLibCalculateClk (PpFuseArray->SclkDpmDid[Index], EffectiveMainPllFreq10KHz) / 100) : 0
399 );
efdesign9884cbce22011-08-04 12:09:17 -0600400 IDS_HDT_CONSOLE (
401 NB_MISC,
402 " SCLK TDP[%d] - 0x%x \n",
403 Index,
404 PpFuseArray->SclkDpmTdpLimit[Index]
405 );
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000406 IDS_HDT_CONSOLE (NB_MISC, " SCLK VID[%d] - 0x%02x\n", Index, PpFuseArray->SclkDpmVid[Index]);
407 }
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]);
414 }
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);
efdesign9884cbce22011-08-04 12:09:17 -0600417 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);
421 IDS_HDT_CONSOLE (
422 NB_MISC, " SclkThermDid - %x(%dMHz)\n",
423 PpFuseArray->SclkThermDid,
424 (PpFuseArray->SclkThermDid != 0) ? (GfxLibCalculateClk (PpFuseArray->SclkThermDid, EffectiveMainPllFreq10KHz) / 100) : 0
425 );
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000426 IDS_HDT_CONSOLE (NB_MISC, "<------------ GNB FUSE END-------------->\n");
427}