blob: e1a39bc106c121b271e585a029b5fd651f18b021 [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * AMD CPU Register Table Related Functions
6 *
7 * Set registers according to a set of register tables
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: CPU
12 * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
13 *
14 */
15/*
16 ******************************************************************************
17 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080018 * Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc.
19 * All rights reserved.
zbao7d94cf92012-07-02 14:19:14 +080020 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080021 * 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.
zbao7d94cf92012-07-02 14:19:14 +080031 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080032 * 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.
zbao7d94cf92012-07-02 14:19:14 +080042 ******************************************************************************
43 */
44
45/*----------------------------------------------------------------------------------------
46 * M O D U L E S U S E D
47 *----------------------------------------------------------------------------------------
48 */
49#include "AGESA.h"
50#include "amdlib.h"
51#include "Ids.h"
52#include "Topology.h"
53#include "OptionMultiSocket.h"
54#include "cpuRegisters.h"
55#include "cpuFamilyTranslation.h"
56#include "Table.h"
57#include "GeneralServices.h"
58#include "cpuServices.h"
59#include "cpuFeatures.h"
60#include "CommonReturns.h"
61#include "cpuL3Features.h"
62#include "Filecode.h"
63CODE_GROUP (G1_PEICC)
64RDATA_GROUP (G1_PEICC)
65
66#define FILECODE PROC_CPU_TABLEHT_FILECODE
67
68extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
69
70/*----------------------------------------------------------------------------------------
71 * D E F I N I T I O N S A N D M A C R O S
72 *----------------------------------------------------------------------------------------
73 */
74
75/*----------------------------------------------------------------------------------------
76 * T Y P E D E F S A N D S T R U C T U R E S
77 *----------------------------------------------------------------------------------------
78 */
79
80/*----------------------------------------------------------------------------------------
81 * 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
82 *----------------------------------------------------------------------------------------
83 */
84
85/*----------------------------------------------------------------------------------------
86 * E X P O R T E D F U N C T I O N S
87 *----------------------------------------------------------------------------------------
88 */
89extern BUILD_OPT_CFG UserOptions;
90
91
92/*---------------------------------------------------------------------------------------*/
93/**
94 * Program HT Phy PCI registers using BKDG values.
95 *
96 * @TableEntryTypeMethod{::HtPhyRegister}.
97 *
98 *
99 * @param[in] Entry The type specific entry data to be implemented (that is written).
100 * @param[in] PlatformConfig Config handle for platform specific information
101 * @param[in] StdHeader Config params for library, services.
102 *
103 */
104VOID
105SetRegisterForHtPhyEntry (
106 IN TABLE_ENTRY_DATA *Entry,
107 IN PLATFORM_CONFIGURATION *PlatformConfig,
108 IN AMD_CONFIG_PARAMS *StdHeader
109 )
110{
111 UINT32 Link;
112 UINT32 MySocket;
113 UINT32 MyModule;
114 AGESA_STATUS IgnoredStatus;
115 UINT32 Ignored;
116 CPU_LOGICAL_ID CpuFamilyRevision;
117 PCI_ADDR CapabilitySet;
118 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
119 BOOLEAN MatchedSublink1;
120 HT_FREQUENCIES Freq0;
121 HT_FREQUENCIES Freq1;
122
123 // Errors: Possible values in unused entry space, extra type features, value range checks.
124 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
125 ASSERT ((Entry->InitialValues[4] == 0) &&
126 ((Entry->HtPhyEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL | HTPHY_LINKTYPE_SL0_AND | HTPHY_LINKTYPE_SL1_AND)) == 0) &&
127 (Entry->HtPhyEntry.Address < HTPHY_REGISTER_MAX));
128
129 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
130 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
131 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
132 GetCpuServicesFromLogicalId (&CpuFamilyRevision, &FamilySpecificServices, StdHeader);
133 Link = 0;
134 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
135 FamilySpecificServices,
136 &CapabilitySet,
137 &Link,
138 &Entry->HtPhyEntry.TypeFeats,
139 &MatchedSublink1,
140 &Freq0,
141 &Freq1,
142 StdHeader)) {
143 FamilySpecificServices->SetHtPhyRegister (FamilySpecificServices, &Entry->HtPhyEntry, CapabilitySet, Link, StdHeader);
144 }
145}
146
147/*---------------------------------------------------------------------------------------*/
148/**
149 * Program a range of HT Phy PCI registers using BKDG values.
150 *
151 * @TableEntryTypeMethod{::HtPhyRangeRegister}.
152 *
153 *
154 * @param[in] Entry The type specific entry data to be implemented (that is written).
155 * @param[in] PlatformConfig Config handle for platform specific information
156 * @param[in] StdHeader Config params for library, services.
157 *
158 */
159VOID
160SetRegisterForHtPhyRangeEntry (
161 IN TABLE_ENTRY_DATA *Entry,
162 IN PLATFORM_CONFIGURATION *PlatformConfig,
163 IN AMD_CONFIG_PARAMS *StdHeader
164 )
165{
166 UINT32 Link;
167 UINT32 MySocket;
168 UINT32 MyModule;
169 AGESA_STATUS IgnoredStatus;
170 UINT32 Ignored;
171 CPU_LOGICAL_ID CpuFamilyRevision;
172 PCI_ADDR CapabilitySet;
173 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
174 HT_PHY_TYPE_ENTRY_DATA CurrentHtPhyRegister;
175 BOOLEAN MatchedSublink1;
176 HT_FREQUENCIES Freq0;
177 HT_FREQUENCIES Freq1;
178
179 // Errors: Possible values in unused entry space, extra type features, value range checks.
180 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
181 ASSERT (((Entry->HtPhyRangeEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL)) == 0) &&
182 (Entry->HtPhyRangeEntry.LowAddress <= Entry->HtPhyRangeEntry.HighAddress) &&
183 (Entry->HtPhyRangeEntry.HighAddress < HTPHY_REGISTER_MAX) &&
184 (Entry->HtPhyRangeEntry.HighAddress != 0));
185
186 CurrentHtPhyRegister.Mask = Entry->HtPhyRangeEntry.Mask;
187 CurrentHtPhyRegister.Data = Entry->HtPhyRangeEntry.Data;
188 CurrentHtPhyRegister.TypeFeats = Entry->HtPhyRangeEntry.TypeFeats;
189
190 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
191 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
192 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
193 GetCpuServicesFromLogicalId (&CpuFamilyRevision, &FamilySpecificServices, StdHeader);
194 Link = 0;
195 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
196 FamilySpecificServices,
197 &CapabilitySet,
198 &Link,
199 &Entry->HtPhyRangeEntry.TypeFeats,
200 &MatchedSublink1,
201 &Freq0,
202 &Freq1,
203 StdHeader)) {
204 for (CurrentHtPhyRegister.Address = Entry->HtPhyRangeEntry.LowAddress;
205 CurrentHtPhyRegister.Address <= Entry->HtPhyRangeEntry.HighAddress;
206 CurrentHtPhyRegister.Address++) {
207 FamilySpecificServices->SetHtPhyRegister (FamilySpecificServices, &CurrentHtPhyRegister, CapabilitySet, Link, StdHeader);
208 }
209 }
210}
211
212/*----------------------------------------------------------------------------------------*/
213/**
214 * Is PackageLink an Internal Link?
215 *
216 * This is a test for the logical link match codes in the user interface, not a test for
217 * the actual northbridge links.
218 *
219 * @param[in] PackageLink The link
220 *
221 * @retval TRUE This is an internal link
222 * @retval FALSE This is not an internal link
223 */
224BOOLEAN
225STATIC
226IsDeemphasisLinkInternal (
227 IN UINT32 PackageLink
228 )
229{
230 return (BOOLEAN) ((PackageLink <= HT_LIST_MATCH_INTERNAL_LINK_2) && (PackageLink >= HT_LIST_MATCH_INTERNAL_LINK_0));
231}
232
233/*----------------------------------------------------------------------------------------*/
234/**
235 * Get the Package Link number, for the current node and real link number.
236 *
237 * Based on the link to package link mapping from BKDG, look up package link for
238 * the input link on the internal node number corresponding to the current core's node.
239 * For single module processors, the northbridge link and package link are the same.
240 *
241 * @param[in] Link the link on the current node.
242 * @param[in] FamilySpecificServices CPU specific support interface.
243 * @param[in] StdHeader Config params for library, services.
244 *
245 * @return the Package Link, HT_LIST_TERMINAL Not connected in package, HT_LIST_MATCH_INTERNAL_LINK package internal link.
246 *
247 */
248UINT32
249STATIC
250LookupPackageLink (
251 IN UINT32 Link,
252 IN CPU_SPECIFIC_SERVICES *FamilySpecificServices,
253 IN AMD_CONFIG_PARAMS *StdHeader
254 )
255{
256 UINT32 PackageLinkMapItem;
257 UINT32 PackageLink;
258 AP_MAIL_INFO ApMailbox;
259
260 PackageLink = HT_LIST_TERMINAL;
261
262 GetApMailbox (&ApMailbox.Info, StdHeader);
263
264 if (ApMailbox.Fields.ModuleType != 0) {
265 ASSERT (FamilySpecificServices->PackageLinkMap != NULL);
266 // Use table to find this module's package link
267 PackageLinkMapItem = 0;
268 while ((*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].Link != HT_LIST_TERMINAL) {
269 if (((*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].Module == ApMailbox.Fields.Module) &&
270 ((*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].Link == Link)) {
271 PackageLink = (*FamilySpecificServices->PackageLinkMap)[PackageLinkMapItem].PackageLink;
272 break;
273 }
274 PackageLinkMapItem++;
275 }
276 } else {
277 PackageLink = Link;
278 }
279 return PackageLink;
280}
281
282/*---------------------------------------------------------------------------------------*/
283/**
284 * Get the platform's specified deemphasis levels for the current link.
285 *
286 * Search the platform's list for a match to the current link and also matching frequency.
287 * If a match is found, use the specified deemphasis levels.
288 *
289 * @param[in] Socket The current Socket.
290 * @param[in] Link The link on that socket.
291 * @param[in] Frequency The frequency the link is set to.
292 * @param[in] PlatformConfig Config handle for platform specific information
293 * @param[in] FamilySpecificServices CPU specific support interface.
294 * @param[in] StdHeader Config params for library, services.
295 *
296 * @return The Deemphasis values for the link.
297 */
298UINT32
299STATIC
300GetLinkDeemphasis (
301 IN UINT32 Socket,
302 IN UINT32 Link,
303 IN HT_FREQUENCIES Frequency,
304 IN PLATFORM_CONFIGURATION *PlatformConfig,
305 IN CPU_SPECIFIC_SERVICES *FamilySpecificServices,
306 IN AMD_CONFIG_PARAMS *StdHeader
307 )
308{
309 UINT32 Result;
310 CPU_HT_DEEMPHASIS_LEVEL *Match;
311 UINT32 PackageLink;
312
313 PackageLink = LookupPackageLink (Link, FamilySpecificServices, StdHeader);
314 // All External and Internal links have deemphasis level none as the default.
315 // However, it is expected that the platform BIOS will provide deemphasis levels for the external links.
316 Result = ((DCV_LEVEL_NONE) | (DEEMPHASIS_LEVEL_NONE));
317
318 if (PlatformConfig->PlatformDeemphasisList != NULL) {
319 Match = PlatformConfig->PlatformDeemphasisList;
320 while (Match->Socket != HT_LIST_TERMINAL) {
321 if (((Match->Socket == Socket) || (Match->Socket == HT_LIST_MATCH_ANY)) &&
322 ((Match->Link == PackageLink) ||
323 ((Match->Link == HT_LIST_MATCH_ANY) && (!IsDeemphasisLinkInternal (PackageLink))) ||
324 ((Match->Link == HT_LIST_MATCH_INTERNAL_LINK) && (IsDeemphasisLinkInternal (PackageLink)))) &&
325 ((Match->LoFreq <= Frequency) && (Match->HighFreq >= Frequency))) {
326 // Found a match, get the deemphasis value.
327 ASSERT ((MaxPlatformDeemphasisLevel > Match->DcvDeemphasis) | (MaxPlatformDeemphasisLevel > Match->ReceiverDeemphasis));
328 Result = ((1 << Match->DcvDeemphasis) | (1 << Match->ReceiverDeemphasis));
329 break;
330 } else {
331 Match++;
332 }
333 }
334 }
335 return Result;
336}
337
338/*---------------------------------------------------------------------------------------*/
339/**
340 * Program Deemphasis registers using BKDG values, for the platform specified levels.
341 *
342 * @TableEntryTypeMethod{::DeemphasisRegister}.
343 *
344 *
345 * @param[in] Entry The type specific entry data to be implemented (that is written).
346 * @param[in] PlatformConfig Config handle for platform specific information
347 * @param[in] StdHeader Config params for library, services.
348 *
349 */
350VOID
351SetRegisterForDeemphasisEntry (
352 IN TABLE_ENTRY_DATA *Entry,
353 IN PLATFORM_CONFIGURATION *PlatformConfig,
354 IN AMD_CONFIG_PARAMS *StdHeader
355 )
356{
357 UINT32 Link;
358 UINT32 MySocket;
359 UINT32 MyModule;
360 AGESA_STATUS IgnoredStatus;
361 UINT32 Ignored;
362 CPU_LOGICAL_ID CpuFamilyRevision;
363 PCI_ADDR CapabilitySet;
364 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
365 BOOLEAN MatchedSublink1;
366 HT_FREQUENCIES Freq0;
367 HT_FREQUENCIES Freq1;
368
369 // Errors: Possible values in unused entry space, extra type features, value range checks.
370 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
371 ASSERT (((Entry->DeemphasisEntry.Levels.DeemphasisValues & ~(VALID_DEEMPHASIS_LEVELS)) == 0) &&
372 ((Entry->DeemphasisEntry.HtPhyEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL)) == 0) &&
373 (Entry->DeemphasisEntry.HtPhyEntry.Address < HTPHY_REGISTER_MAX));
374
375 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
376 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
377 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
378 GetCpuServicesFromLogicalId (&CpuFamilyRevision, &FamilySpecificServices, StdHeader);
379 Link = 0;
380 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
381 FamilySpecificServices,
382 &CapabilitySet,
383 &Link,
384 &Entry->DeemphasisEntry.HtPhyEntry.TypeFeats,
385 &MatchedSublink1,
386 &Freq0,
387 &Freq1,
388 StdHeader)) {
389 if (DoesEntryTypeSpecificInfoMatch (
390 GetLinkDeemphasis (
391 MySocket,
392 (MatchedSublink1 ? (Link + 4) : Link),
393 (MatchedSublink1 ? Freq1 : Freq0),
394 PlatformConfig,
395 FamilySpecificServices,
396 StdHeader),
397 Entry->DeemphasisEntry.Levels.DeemphasisValues)) {
398 FamilySpecificServices->SetHtPhyRegister (
399 FamilySpecificServices,
400 &Entry->DeemphasisEntry.HtPhyEntry,
401 CapabilitySet,
402 Link,
403 StdHeader
404 );
405 IDS_HDT_CONSOLE (HT_TRACE, "Socket %d Module %d Sub-link %1d :\n ----> running on HT3, %s Level is %s\n",
406 MySocket, MyModule,
407 ((Entry->DeemphasisEntry.HtPhyEntry.TypeFeats.HtPhyLinkValue & HTPHY_LINKTYPE_SL0_ALL) != 0) ? Link : (Link + 4),
408 ((Entry->DeemphasisEntry.Levels.DeemphasisValues & DCV_LEVELS_ALL) != 0) ? "DCV" : "Deemphasis",
409 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL_NONE) ? " 0 dB" :
410 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__3) ? " - 3 dB" :
411 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__6) ? " - 6 dB" :
412 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__6) ? " - 6 dB" :
413 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__8) ? " - 8 dB" :
414 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__11) ? " - 11 dB" :
415 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DEEMPHASIS_LEVEL__11_8) ? " - 11 dB postcursor with - 8 dB precursor" :
416 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL_NONE) ? " 0 dB" :
417 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__2) ? " - 2 dB" :
418 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__3) ? " - 3 dB" :
419 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__5) ? " - 5 dB" :
420 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__6) ? " - 6 dB" :
421 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__7) ? " - 7 dB" :
422 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__8) ? " - 8 dB" :
423 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__9) ? " - 9 dB" :
424 (Entry->DeemphasisEntry.Levels.DeemphasisValues == DCV_LEVEL__11) ? " - 11 dB" : "Undefined");
425 }
426 }
427}
428
429/*---------------------------------------------------------------------------------------*/
430/**
431 * Program HT Phy PCI registers which have complex frequency dependencies.
432 *
433 * @TableEntryTypeMethod{::HtPhyFreqRegister}.
434 *
435 * After matching a link for HT Features, check if the HT frequency matches the given range.
436 * If it does, get the northbridge frequency limits for implemented NB P-states and check if
437 * each matches the given range - range 0 and range 1 for each NB frequency, respectively.
438 * If all matches, apply the entry.
439 *
440 * @param[in] Entry The type specific entry data to be implemented (that is written).
441 * @param[in] PlatformConfig Config handle for platform specific information
442 * @param[in] StdHeader Config params for library, services.
443 *
444 */
445VOID
446SetRegisterForHtPhyFreqEntry (
447 IN TABLE_ENTRY_DATA *Entry,
448 IN PLATFORM_CONFIGURATION *PlatformConfig,
449 IN AMD_CONFIG_PARAMS *StdHeader
450 )
451{
452 UINT32 Link;
453 UINT32 MySocket;
454 UINT32 MyModule;
455 AGESA_STATUS IgnoredStatus;
456 UINT32 Ignored;
457 CPU_LOGICAL_ID CpuFamilyRevision;
458 PCI_ADDR CapabilitySet;
459 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
460 BOOLEAN MatchedSublink1;
461 HT_FREQUENCIES Freq0;
462 HT_FREQUENCIES Freq1;
463 BOOLEAN Temp1;
464 BOOLEAN Temp2;
465 UINT32 NbFreq0;
466 UINT32 NbFreq1;
467 UINT32 NbDivisor0;
468 UINT32 NbDivisor1;
469
470 // Errors: extra type features, value range checks.
471 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
472 ASSERT (((Entry->HtPhyFreqEntry.HtPhyEntry.TypeFeats.HtPhyLinkValue & ~(HTPHY_LINKTYPE_ALL)) == 0) &&
473 (Entry->HtPhyFreqEntry.HtPhyEntry.Address < HTPHY_REGISTER_MAX));
474
475 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
476 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
477 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
478 GetCpuServicesFromLogicalId (&CpuFamilyRevision, &FamilySpecificServices, StdHeader);
479 Link = 0;
480 while (FamilySpecificServices->NextLinkHasHtPhyFeats (
481 FamilySpecificServices,
482 &CapabilitySet,
483 &Link,
484 &Entry->HtPhyFreqEntry.HtPhyEntry.TypeFeats,
485 &MatchedSublink1,
486 &Freq0,
487 &Freq1,
488 StdHeader)) {
489 // Check the HT Frequency for match to the range.
490 if (IsEitherCountInRange (
491 (MatchedSublink1 ? Freq1 : Freq0),
492 (MatchedSublink1 ? Freq1 : Freq0),
493 Entry->HtPhyFreqEntry.HtFreqCounts.HtFreqCountRanges)) {
494 // Get the NB Frequency, convert to 100's of MHz, then convert to equivalent HT encoding. This supports
495 // NB frequencies from 800 MHz to 2600 MHz, which is currently greater than any processor supports.
496 OptionMultiSocketConfiguration.GetSystemNbPstateSettings (
497 (UINT32) 0,
498 PlatformConfig,
499 &NbFreq0,
500 &NbDivisor0,
501 &Temp1,
502 &Temp2,
503 StdHeader);
504
505 if (OptionMultiSocketConfiguration.GetSystemNbPstateSettings (
506 (UINT32) 1,
507 PlatformConfig,
508 &NbFreq1,
509 &NbDivisor1,
510 &Temp1,
511 &Temp2,
512 StdHeader)) {
513 ASSERT (NbDivisor1 != 0);
514 NbFreq1 = (NbFreq1 / NbDivisor1);
515 NbFreq1 = (NbFreq1 / 100);
516 NbFreq1 = (NbFreq1 / 2) + 1;
517 } else {
518 NbFreq1 = 0;
519 }
520
521 ASSERT (NbDivisor0 != 0);
522 NbFreq0 = (NbFreq0 / NbDivisor0);
523 NbFreq0 = (NbFreq0 / 100);
524 NbFreq0 = (NbFreq0 / 2) + 1;
525 if (IsEitherCountInRange (NbFreq0, NbFreq1, Entry->HtPhyFreqEntry.NbFreqCounts.HtFreqCountRanges)) {
526 FamilySpecificServices->SetHtPhyRegister (
527 FamilySpecificServices,
528 &Entry->HtPhyFreqEntry.HtPhyEntry,
529 CapabilitySet,
530 Link,
531 StdHeader);
532 }
533 }
534 }
535}
536
537
538/*---------------------------------------------------------------------------------------*/
539/**
540 * Perform the HT Phy Performance Profile Register Entry.
541 *
542 * @TableEntryTypeMethod{::HtPhyProfileRegister}.
543 *
544 * @param[in] Entry The HT Phy register entry to perform
545 * @param[in] PlatformConfig Config handle for platform specific information
546 * @param[in] StdHeader Config handle for library and services.
547 *
548 */
549VOID
550SetRegisterForHtPhyProfileEntry (
551 IN TABLE_ENTRY_DATA *Entry,
552 IN PLATFORM_CONFIGURATION *PlatformConfig,
553 IN AMD_CONFIG_PARAMS *StdHeader
554 )
555{
556 PERFORMANCE_PROFILE_FEATS PlatformProfile;
557 TABLE_ENTRY_DATA HtPhyEntry;
558
559 // Errors: Possible values in unused entry space, extra type features, value range checks.
560 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
561 ASSERT (((Entry->HtPhyProfileEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0) &&
562 (Entry->InitialValues[5] == 0));
563
564 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
565 if (DoesEntryTypeSpecificInfoMatch (
566 PlatformProfile.PerformanceProfileValue,
567 Entry->HtPhyProfileEntry.TypeFeats.PerformanceProfileValue)) {
568 LibAmdMemFill (&HtPhyEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
569 HtPhyEntry.HtPhyEntry = Entry->HtPhyProfileEntry.HtPhyEntry;
570 SetRegisterForHtPhyEntry (&HtPhyEntry, PlatformConfig, StdHeader);
571 }
572}
573
574/*---------------------------------------------------------------------------------------*/
575/**
576 * Perform the HT Host PCI Register Entry.
577 *
578 * @TableEntryTypeMethod{::HtHostPciRegister}.
579 *
580 * Make the current core's PCI address with the function and register for the entry.
581 * For all HT links, check the link's feature set for a match to the entry.
582 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
583 *
584 * @param[in] Entry The PCI register entry to perform
585 * @param[in] PlatformConfig Config handle for platform specific information
586 * @param[in] StdHeader Config handle for library and services.
587 *
588 */
589VOID
590SetRegisterForHtHostEntry (
591 IN TABLE_ENTRY_DATA *Entry,
592 IN PLATFORM_CONFIGURATION *PlatformConfig,
593 IN AMD_CONFIG_PARAMS *StdHeader
594 )
595{
596 UINTN Link;
597 UINT32 MySocket;
598 UINT32 MyModule;
599 AGESA_STATUS IgnoredStatus;
600 UINT32 Ignored;
601 CPU_LOGICAL_ID CpuFamilyRevision;
602 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
603 PCI_ADDR CapabilitySet;
604 PCI_ADDR PciAddress;
605 HT_HOST_FEATS HtHostFeats;
606 UINT32 RegisterData;
607
608 // Errors: Possible values in unused entry space, extra type features, value range checks.
609 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
610 ASSERT ((Entry->InitialValues[4] == 0) &&
611 ((Entry->HtHostEntry.TypeFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0) &&
612 (Entry->HtHostEntry.Address.Address.Register < HT_LINK_HOST_CAP_MAX));
613
614 HtHostFeats.HtHostValue = 0;
615 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
616 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
617 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
618 GetCpuServicesFromLogicalId (&CpuFamilyRevision, &FamilySpecificServices, StdHeader);
619 Link = 0;
620 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
621 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtHostEntry.TypeFeats.HtHostValue)) {
622 // Do the HT Host PCI register update.
623 PciAddress = CapabilitySet;
624 PciAddress.Address.Register += Entry->HtHostEntry.Address.Address.Register;
625 LibAmdPciRead (AccessWidth32, PciAddress, &RegisterData, StdHeader);
626 RegisterData = RegisterData & (~(Entry->HtHostEntry.Mask));
627 RegisterData = RegisterData | Entry->HtHostEntry.Data;
628 LibAmdPciWrite (AccessWidth32, PciAddress, &RegisterData, StdHeader);
629 }
630 }
631}
632
633/*---------------------------------------------------------------------------------------*/
634/**
635 * Perform the HT Host Performance PCI Register Entry.
636 *
637 * @TableEntryTypeMethod{::HtHostPerfPciRegister}.
638 *
639 * Make the current core's PCI address with the function and register for the entry.
640 * For all HT links, check the link's feature set for a match to the entry.
641 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
642 *
643 * @param[in] Entry The PCI register entry to perform
644 * @param[in] PlatformConfig Config handle for platform specific information
645 * @param[in] StdHeader Config handle for library and services.
646 *
647 */
648VOID
649SetRegisterForHtHostPerfEntry (
650 IN TABLE_ENTRY_DATA *Entry,
651 IN PLATFORM_CONFIGURATION *PlatformConfig,
652 IN AMD_CONFIG_PARAMS *StdHeader
653 )
654{
655 PERFORMANCE_PROFILE_FEATS PlatformProfile;
656 TABLE_ENTRY_DATA HtHostPciTypeEntryData;
657
658 // Errors: Possible values in unused entry space, extra type features, value range checks.
659 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
660 ASSERT ((Entry->InitialValues[5] == 0) &&
661 ((Entry->HtHostEntry.TypeFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0) &&
662 (Entry->HtHostEntry.Address.Address.Register < HT_LINK_HOST_CAP_MAX));
663
664 // Check for any performance profile features.
665 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
666 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue,
667 Entry->HtHostPerfEntry.PerformanceFeats.PerformanceProfileValue)) {
668 // Perform HT Host entry process.
669 LibAmdMemFill (&HtHostPciTypeEntryData, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
670 HtHostPciTypeEntryData.HtHostEntry = Entry->HtHostPerfEntry.HtHostEntry;
671 SetRegisterForHtHostEntry (&HtHostPciTypeEntryData, PlatformConfig, StdHeader);
672 }
673}
674
675/*---------------------------------------------------------------------------------------*/
676/**
677 * Set the HT Link Token Count registers.
678 *
679 * @TableEntryTypeMethod{::HtTokenPciRegister}.
680 *
681 * Make the current core's PCI address with the function and register for the entry.
682 * Check the performance profile features.
683 * For all HT links, check the link's feature set for a match to the entry.
684 * Read - Modify - Write the PCI register, clearing masked bits, and setting the data bits.
685 *
686 * @param[in] Entry The Link Token register entry to perform
687 * @param[in] PlatformConfig Config handle for platform specific information
688 * @param[in] StdHeader Config handle for library and services.
689 *
690 */
691VOID
692SetRegisterForHtLinkTokenEntry (
693 IN TABLE_ENTRY_DATA *Entry,
694 IN PLATFORM_CONFIGURATION *PlatformConfig,
695 IN AMD_CONFIG_PARAMS *StdHeader
696 )
697{
698 UINTN Link;
699 UINT32 MySocket;
700 UINT32 MyModule;
701 AGESA_STATUS IgnoredStatus;
702 UINT32 Ignored;
703 CPU_LOGICAL_ID CpuFamilyRevision;
704 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
705 PCI_ADDR CapabilitySet;
706 HT_HOST_FEATS HtHostFeats;
707 PERFORMANCE_PROFILE_FEATS PlatformProfile;
708 UINTN ProcessorCount;
709 UINTN SystemDegree;
710 UINT32 RegisterData;
711 PCI_ADDR PciAddress;
712
713 // Errors: Possible values in unused entry space, extra type features, value range checks.
714 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
715 ASSERT (((Entry->HtTokenEntry.LinkFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0) &&
716 ((Entry->HtTokenEntry.PerformanceFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0) &&
717 (Entry->HtTokenEntry.Mask != 0));
718
719 HtHostFeats.HtHostValue = 0;
720 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
721 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
722 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
723 GetCpuServicesFromLogicalId (&CpuFamilyRevision, &FamilySpecificServices, StdHeader);
724
725 // Check if the actual processor count and SystemDegree are in either range.
726 ProcessorCount = GetNumberOfProcessors (StdHeader);
727 SystemDegree = GetSystemDegree (StdHeader);
728 if (IsEitherCountInRange (ProcessorCount, SystemDegree, Entry->HtTokenEntry.ConnectivityCount.ConnectivityCountRanges)) {
729 // Check for any performance profile features.
730 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
731 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue,
732 Entry->HtTokenEntry.PerformanceFeats.PerformanceProfileValue)) {
733 // Check the link features.
734 Link = 0;
735 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
736 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtTokenEntry.LinkFeats.HtHostValue)) {
737 // Do the HT Host PCI register update. Token register are four registers, sublink 0 and 1 share fields.
738 // If sublink 0 is unconnected, we should let sublink 1 match. If the links are ganged, of course only sublink 0 matches.
739 // If the links are unganged and both connected, the BKDG settings are for both coherent.
740 PciAddress = CapabilitySet;
741 PciAddress.Address.Register = Entry->HtTokenEntry.Address.Address.Register +
742 ((Link > 3) ? (((UINT32)Link - 4) * 4) : ((UINT32)Link * 4));
743 PciAddress.Address.Function = Entry->HtTokenEntry.Address.Address.Function;
744 LibAmdPciRead (AccessWidth32, PciAddress, &RegisterData, StdHeader);
745 RegisterData = RegisterData & (~(Entry->HtTokenEntry.Mask));
746 RegisterData = RegisterData | Entry->HtTokenEntry.Data;
747 LibAmdPciWrite (AccessWidth32, PciAddress, &RegisterData, StdHeader);
748 }
749 }
750 }
751 }
752}
753
754/*---------------------------------------------------------------------------------------*/
755/**
756 * Perform the Processor Token Counts PCI Register Entry.
757 *
758 * @TableEntryTypeMethod{::TokenPciRegister}.
759 *
760 * The table criteria then translate as:
761 * - 2 Socket, half populated == Degree 1
762 * - 4 Socket, half populated == Degree 2
763 * - 2 Socket, fully populated == Degree 3
764 * - 4 Socket, fully populated == Degree > 3. (4 or 5 if 3P, 6 if 4P)
765 *
766 * @param[in] Entry The PCI register entry to perform
767 * @param[in] PlatformConfig Config handle for platform specific information
768 * @param[in] StdHeader Config handle for library and services.
769 *
770 */
771VOID
772SetRegisterForTokenPciEntry (
773 IN TABLE_ENTRY_DATA *Entry,
774 IN PLATFORM_CONFIGURATION *PlatformConfig,
775 IN AMD_CONFIG_PARAMS *StdHeader
776 )
777{
778 PERFORMANCE_PROFILE_FEATS PlatformProfile;
779 UINTN SystemDegree;
780 TABLE_ENTRY_DATA PciEntry;
781
782 // Errors: Possible values in unused entry space, extra type features, value range checks.
783 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
784 ASSERT (((Entry->TokenPciEntry.TypeFeats.PerformanceProfileValue & ~((PERFORMANCE_PROFILE_ALL) | (PERFORMANCE_AND))) == 0));
785
786 GetPerformanceFeatures (&PlatformProfile, PlatformConfig, StdHeader);
787 if (DoesEntryTypeSpecificInfoMatch (PlatformProfile.PerformanceProfileValue, Entry->TokenPciEntry.TypeFeats.PerformanceProfileValue)) {
788 SystemDegree = GetSystemDegree (StdHeader);
789 // Check if the system degree is in the range.
790 if (IsEitherCountInRange (SystemDegree, SystemDegree, Entry->TokenPciEntry.ConnectivityCount.ConnectivityCountRanges)) {
791 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
792 PciEntry.PciEntry = Entry->TokenPciEntry.PciEntry;
793 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
794 }
795 }
796}
797
798/*---------------------------------------------------------------------------------------*/
799/**
800 * Perform the HT Link Feature PCI Register Entry.
801 *
802 * @TableEntryTypeMethod{::HtFeatPciRegister}.
803 *
804 * Set a single field (that is, the register field is not in HT Host capability or a
805 * set of per link registers) in PCI config, based on HT link features and package type.
806 * This code is used for two cases: single link processors and multilink processors.
807 * For single link cases, the link will be tested for a match to the HT Features for the link.
808 * For multilink processors, the entry will match if @b any link is found which matches.
809 * For example, a setting can be applied based on coherent HT3 by matching coherent AND HT3.
810 *
811 * Make the core's PCI address. Check the package type (currently more important to the single link case),
812 * and if matching, iterate through all links checking for an HT feature match until found or exhausted.
813 * If a match was found, pass the PCI entry data to the implementer for writing for the current core.
814 *
815 * @param[in] Entry The PCI register entry to perform
816 * @param[in] PlatformConfig Config handle for platform specific information
817 * @param[in] StdHeader Config handle for library and services.
818 *
819 */
820VOID
821SetRegisterForHtFeaturePciEntry (
822 IN TABLE_ENTRY_DATA *Entry,
823 IN PLATFORM_CONFIGURATION *PlatformConfig,
824 IN AMD_CONFIG_PARAMS *StdHeader
825 )
826{
827 UINTN Link;
828 UINT32 MySocket;
829 UINT32 MyModule;
830 AGESA_STATUS IgnoredStatus;
831 UINT32 Ignored;
832 CPU_LOGICAL_ID CpuFamilyRevision;
833 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
834 PCI_ADDR CapabilitySet;
835 HT_HOST_FEATS HtHostFeats;
836 UINT32 ProcessorPackageType;
837 BOOLEAN IsMatch;
838 TABLE_ENTRY_DATA PciEntry;
839
840 // Errors: Possible values in unused entry space, extra type features, value range checks.
841 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
842 ASSERT ((Entry->HtFeatPciEntry.PciEntry.Mask != 0) &&
843 ((Entry->HtFeatPciEntry.LinkFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0));
844
845 HtHostFeats.HtHostValue = 0;
846 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
847 PciEntry.PciEntry = Entry->HtFeatPciEntry.PciEntry;
848 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
849 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
850 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
851 GetCpuServicesFromLogicalId (&CpuFamilyRevision, &FamilySpecificServices, StdHeader);
852
853 ASSERT ((Entry->HtFeatPciEntry.PackageType.PackageTypeValue & ~(PACKAGE_TYPE_ALL)) == 0);
854
855 ProcessorPackageType = LibAmdGetPackageType (StdHeader);
856 if (DoesEntryTypeSpecificInfoMatch (ProcessorPackageType, Entry->HtFeatPciEntry.PackageType.PackageTypeValue)) {
857 IsMatch = FALSE;
858 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
859 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtFeatPciEntry.LinkFeats.HtHostValue)) {
860 IsMatch = TRUE;
861 break;
862 }
863 }
864 if (IsMatch) {
865 // Do the PCI register update.
866 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
867 }
868 }
869}
870
871/*---------------------------------------------------------------------------------------*/
872/**
873 * Perform the HT Link PCI Register Entry.
874 *
875 * @TableEntryTypeMethod{::HtLinkPciRegister}.
876 *
877 * Make the current core's PCI address with the function and register for the entry.
878 * Registers are processed for match per link, assuming sequential PCI address per link.
879 * Read - Modify - Write each matching link's PCI register, clearing masked bits, and setting the data bits.
880 *
881 * @param[in] Entry The PCI register entry to perform
882 * @param[in] PlatformConfig Config handle for platform specific information
883 * @param[in] StdHeader Config handle for library and services.
884 *
885 */
886VOID
887SetRegisterForHtLinkPciEntry (
888 IN TABLE_ENTRY_DATA *Entry,
889 IN PLATFORM_CONFIGURATION *PlatformConfig,
890 IN AMD_CONFIG_PARAMS *StdHeader
891 )
892{
893 UINTN Link;
894 UINT32 MySocket;
895 UINT32 MyModule;
896 AGESA_STATUS IgnoredStatus;
897 UINT32 Ignored;
898 CPU_LOGICAL_ID CpuFamilyRevision;
899 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
900 PCI_ADDR CapabilitySet;
901 HT_HOST_FEATS HtHostFeats;
902 TABLE_ENTRY_DATA PciEntry;
903
904 // Errors: Possible values in unused entry space, extra type features, value range checks.
905 // Check that the entry type is correct and the actual supplied entry data is appropriate for that entry.
906 ASSERT ((Entry->HtLinkPciEntry.PciEntry.Mask != 0) &&
907 ((Entry->HtLinkPciEntry.LinkFeats.HtHostValue & ~((HT_HOST_FEATURES_ALL) | (HT_HOST_AND))) == 0));
908
909 HtHostFeats.HtHostValue = 0;
910 LibAmdMemFill (&PciEntry, 0, sizeof (TABLE_ENTRY_DATA), StdHeader);
911 PciEntry.PciEntry = Entry->HtLinkPciEntry.PciEntry;
912 IdentifyCore (StdHeader, &MySocket, &MyModule, &Ignored, &IgnoredStatus);
913 GetPciAddress (StdHeader, MySocket, MyModule, &CapabilitySet, &IgnoredStatus);
914 GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
915 GetCpuServicesFromLogicalId (&CpuFamilyRevision, &FamilySpecificServices, StdHeader);
916
917 Link = 0;
918 while (FamilySpecificServices->GetNextHtLinkFeatures (FamilySpecificServices, &Link, &CapabilitySet, &HtHostFeats, StdHeader)) {
919 if (DoesEntryTypeSpecificInfoMatch (HtHostFeats.HtHostValue, Entry->HtLinkPciEntry.LinkFeats.HtHostValue)) {
920 // Do the update to the link's non-Host PCI register, based on the entry address.
921 PciEntry.PciEntry.Address = Entry->HtLinkPciEntry.PciEntry.Address;
922 PciEntry.PciEntry.Address.Address.Register = PciEntry.PciEntry.Address.Address.Register + ((UINT32)Link * 4);
923 SetRegisterForPciEntry (&PciEntry, PlatformConfig, StdHeader);
924 }
925 }
926}
927