AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / cpuFamilyTranslation.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD CPU Family Translation functions.
6  *
7  *
8  * @xrefitem bom "File Content Label" "Release Content"
9  * @e project:      AGESA
10  * @e sub-project:  CPU/Interface
11  * @e \$Revision: 56322 $   @e \$Date: 2011-07-11 16:51:42 -0600 (Mon, 11 Jul 2011) $
12  *
13  */
14 /*
15  ******************************************************************************
16  *
17  * Copyright (C) 2012 Advanced Micro Devices, Inc.
18  * All rights reserved.
19  *
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions are met:
22  *     * Redistributions of source code must retain the above copyright
23  *       notice, this list of conditions and the following disclaimer.
24  *     * Redistributions in binary form must reproduce the above copyright
25  *       notice, this list of conditions and the following disclaimer in the
26  *       documentation and/or other materials provided with the distribution.
27  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
28  *       its contributors may be used to endorse or promote products derived
29  *       from this software without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  *
42  ******************************************************************************
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 "cpuRegisters.h"
53 #include "CommonReturns.h"
54 #include "GeneralServices.h"
55 #include "cpuFamilyTranslation.h"
56 #include "Filecode.h"
57 CODE_GROUP (G1_PEICC)
58 RDATA_GROUP (G2_PEI)
59
60 #define FILECODE PROC_CPU_CPUFAMILYTRANSLATION_FILECODE
61
62 /*----------------------------------------------------------------------------------------
63  *                   D E F I N I T I O N S    A N D    M A C R O S
64  *----------------------------------------------------------------------------------------
65  */
66
67 /*----------------------------------------------------------------------------------------
68  *                  T Y P E D E F S     A N D     S T R U C T U R E S
69  *----------------------------------------------------------------------------------------
70  */
71
72 CONST CPU_SPECIFIC_SERVICES ROMDATA cpuNullServices =
73 {
74   0,
75   (PF_CPU_DISABLE_PSTATE) CommonReturnAgesaSuccess,
76   (PF_CPU_TRANSITION_PSTATE) CommonReturnAgesaSuccess,
77   (PF_CPU_GET_IDD_MAX) CommonReturnFalse,
78   (PF_CPU_GET_TSC_RATE) CommonReturnAgesaSuccess,
79   (PF_CPU_GET_NB_FREQ) CommonReturnAgesaSuccess,
80   (PF_CPU_GET_MIN_MAX_NB_FREQ) CommonReturnAgesaSuccess,
81   (PF_CPU_GET_NB_PSTATE_INFO) CommonReturnFalse,
82   (PF_CPU_IS_NBCOF_INIT_NEEDED) CommonReturnAgesaSuccess,
83   (PF_CPU_GET_NB_IDD_MAX) CommonReturnFalse,
84   (PF_CPU_AP_INITIAL_LAUNCH) CommonReturnFalse,
85   (PF_CPU_NUMBER_OF_PHYSICAL_CORES) CommonReturnZero8,
86   (PF_CPU_AMD_GET_AP_MAILBOX_FROM_HARDWARE) CommonReturnAgesaSuccess,
87   (PF_CPU_SET_AP_CORE_NUMBER) CommonVoid,
88   (PF_CPU_GET_AP_CORE_NUMBER) CommonReturnZero32,
89   (PF_CPU_TRANSFER_AP_CORE_NUMBER) CommonVoid,
90   (PF_CORE_ID_POSITION_IN_INITIAL_APIC_ID) CommonReturnAgesaSuccess,
91   (PF_CPU_SAVE_FEATURES) CommonReturnAgesaSuccess,
92   (PF_CPU_WRITE_FEATURES) CommonReturnAgesaSuccess,
93   (PF_CPU_SET_WARM_RESET_FLAG) CommonReturnAgesaSuccess,
94   (PF_CPU_GET_WARM_RESET_FLAG) CommonReturnAgesaSuccess,
95   GetEmptyArray,
96   GetEmptyArray,
97   GetEmptyArray,
98   GetEmptyArray,
99   GetEmptyArray,
100   GetEmptyArray,
101   GetEmptyArray,
102   (PF_CPU_GET_PLATFORM_TYPE_SPECIFIC_INFO) CommonReturnAgesaSuccess,
103   (PF_IS_NB_PSTATE_ENABLED) CommonReturnFalse,
104   (PF_NEXT_LINK_HAS_HTFPY_FEATS) CommonReturnFalse,
105   (PF_SET_HT_PHY_REGISTER) CommonVoid,
106   (PF_GET_NEXT_HT_LINK_FEATURES) CommonVoid,
107   NULL,
108   NULL,
109   NULL,
110   NULL,
111   InitCacheDisabled,
112   (PF_GET_EARLY_INIT_TABLE) CommonVoid
113 };
114
115 /*----------------------------------------------------------------------------------------
116  *           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
117  *----------------------------------------------------------------------------------------
118  */
119 VOID
120 STATIC
121 GetCpuServices (
122   IN       CPU_FAMILY_SUPPORT_TABLE *FamilyTable,
123   IN       UINT64            *MatchData,
124      OUT   CONST VOID        **CpuServices,
125   IN       AMD_CONFIG_PARAMS *StdHeader
126   );
127
128 /*----------------------------------------------------------------------------------------
129  *                          E X P O R T E D    F U N C T I O N S
130  *----------------------------------------------------------------------------------------
131  */
132 extern CPU_FAMILY_SUPPORT_TABLE CpuSupportedFamiliesTable;
133 extern CPU_FAMILY_ID_XLAT_TABLE CpuSupportedFamilyIdTable;
134
135 /*---------------------------------------------------------------------------------------*/
136 /**
137  *
138  *  Returns the logical ID of the desired processor. This will be obtained by
139  *  reading the CPUID and converting it into a "logical ID" which is not package
140  *  dependent.
141  *
142  *  @param[in]      Socket             Socket
143  *  @param[out]     LogicalId          The Processor's Logical ID
144  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services.
145  *
146  */
147 VOID
148 GetLogicalIdOfSocket (
149   IN       UINT32 Socket,
150      OUT   CPU_LOGICAL_ID *LogicalId,
151   IN       AMD_CONFIG_PARAMS *StdHeader
152   )
153 {
154   UINT32      RawCpuid;
155   PCI_ADDR    PciAddress;
156   AGESA_STATUS AssumedSuccess;
157
158   RawCpuid = 0;
159
160   if (GetPciAddress (StdHeader, (UINT8)Socket, 0, &PciAddress, &AssumedSuccess)) {
161     PciAddress.Address.Function = FUNC_3;
162     PciAddress.Address.Register = CPUID_FMR;
163     LibAmdPciRead (AccessWidth32, PciAddress, &RawCpuid, StdHeader);
164     GetLogicalIdFromCpuid (RawCpuid, LogicalId, StdHeader);
165   } else {
166     LogicalId->Family = 0;
167     LogicalId->Revision = 0;
168     // Logical ID was not found.
169     IDS_ERROR_TRAP;
170   }
171 }
172
173
174 /*---------------------------------------------------------------------------------------*/
175 /**
176  *
177  *  Returns the logical ID of the executing core. This will be obtained by reading
178  *  the CPUID and converting it into a "logical ID" which is not package dependent.
179  *
180  *  @param[out]     LogicalId          The Processor's Logical ID
181  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services.
182  *
183  */
184 VOID
185 GetLogicalIdOfCurrentCore (
186      OUT   CPU_LOGICAL_ID *LogicalId,
187   IN       AMD_CONFIG_PARAMS *StdHeader
188   )
189 {
190   CPUID_DATA  CpuidDataStruct;
191
192   LibAmdCpuidRead (AMD_CPUID_APICID_LPC_BID, &CpuidDataStruct, StdHeader);
193   GetLogicalIdFromCpuid (CpuidDataStruct.EAX_Reg, LogicalId, StdHeader);
194 }
195
196
197 /*---------------------------------------------------------------------------------------*/
198 /**
199  *
200  *  Returns the logical ID of a processor with the given CPUID value. This
201  *  will be obtained by converting it into a "logical ID" which is not package
202  *  dependent.
203  *
204  *  @param[in]      RawCpuid           The unprocessed CPUID value to be translated
205  *  @param[out]     LogicalId          The Processor's Logical ID
206  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services
207  *
208  */
209 VOID
210 GetLogicalIdFromCpuid (
211   IN       UINT32 RawCpuid,
212      OUT   CPU_LOGICAL_ID *LogicalId,
213   IN       AMD_CONFIG_PARAMS *StdHeader
214   )
215 {
216   UINT8       i;
217   UINT8       k;
218   UINT8       NumberOfFamiliesSupported;
219   UINT8       NumberOfLogicalSubFamilies;
220   UINT8       LogicalIdEntries;
221   UINT32      j;
222   UINT32      RawFamily;
223   UINT32      CpuModelAndExtendedModel;
224   UINT64      LogicalFamily;
225   BOOLEAN     IdNotFound;
226   BOOLEAN     FamilyNotFound;
227   CONST PF_CPU_GET_SUBFAMILY_ID_ARRAY *SubFamilyIdPtr;
228   CPU_LOGICAL_ID_XLAT *CpuLogicalIdAndRevPtr;
229   CONST CPU_LOGICAL_ID_FAMILY_XLAT *ImageSupportedId;
230
231   IdNotFound = TRUE;
232   FamilyNotFound = TRUE;
233   CpuLogicalIdAndRevPtr = NULL;
234   ImageSupportedId = CpuSupportedFamilyIdTable.FamilyIdTable;
235   NumberOfFamiliesSupported = CpuSupportedFamilyIdTable.Elements;
236
237   RawFamily = ((RawCpuid & 0xF00) >> 8) + ((RawCpuid & 0xFF00000) >> 20);
238   RawCpuid &= (UINT32) CPU_FMS_MASK;
239   CpuModelAndExtendedModel = (UINT16) ((RawCpuid >> 8) | RawCpuid);
240
241   LogicalId->Family = 0;
242   LogicalId->Revision = 0;
243
244   for (i = 0; i < NumberOfFamiliesSupported && FamilyNotFound; i++) {
245     if (ImageSupportedId[i].Family == RawFamily) {
246       FamilyNotFound = FALSE;
247       LogicalId->Family = ImageSupportedId[i].UnknownRevision.Family;
248       LogicalId->Revision = ImageSupportedId[i].UnknownRevision.Revision;
249
250       NumberOfLogicalSubFamilies = ImageSupportedId[i].Elements;
251       SubFamilyIdPtr = ImageSupportedId[i].SubFamilyIdTable;
252       for (j = 0; j < NumberOfLogicalSubFamilies && IdNotFound; j++) {
253         SubFamilyIdPtr[j] ((CONST CPU_LOGICAL_ID_XLAT **)&CpuLogicalIdAndRevPtr, &LogicalIdEntries, &LogicalFamily, StdHeader);
254         ASSERT (CpuLogicalIdAndRevPtr != NULL);
255         for (k = 0; k < LogicalIdEntries; k++) {
256           if (CpuLogicalIdAndRevPtr[k].RawId == CpuModelAndExtendedModel) {
257             IdNotFound = FALSE;
258             LogicalId->Family = LogicalFamily;
259             LogicalId->Revision = CpuLogicalIdAndRevPtr[k].LogicalId;
260             break;
261           }
262         }
263       }
264     }
265   }
266 }
267
268
269 /*---------------------------------------------------------------------------------------*/
270 /**
271  *
272  *  Retrieves a pointer to the desired processor's family specific services structure.
273  *
274  *  @param[in]      Socket             The Processor in this Socket.
275  *  @param[out]     FunctionTable      The Processor's Family Specific services.
276  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services.
277  *
278  */
279 VOID
280 GetCpuServicesOfSocket (
281   IN       UINT32 Socket,
282      OUT   CONST CPU_SPECIFIC_SERVICES **FunctionTable,
283   IN       AMD_CONFIG_PARAMS *StdHeader
284   )
285 {
286   GetFeatureServicesOfSocket (&CpuSupportedFamiliesTable,
287                               Socket,
288                               (CONST VOID **) FunctionTable,
289                               StdHeader);
290   if (*FunctionTable == NULL) {
291     *FunctionTable = &cpuNullServices;
292   }
293 }
294
295
296 /*---------------------------------------------------------------------------------------*/
297 /**
298  *
299  *  Retrieves a pointer to the desired processor's family specific services structure.
300  *
301  *  @param[in]      FamilyTable        The table to search in.
302  *  @param[in]      Socket             The Processor in this Socket.
303  *  @param[out]     CpuServices        The Processor's Family Specific services.
304  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services.
305  *
306  */
307 VOID
308 GetFeatureServicesOfSocket (
309   IN       CPU_FAMILY_SUPPORT_TABLE *FamilyTable,
310   IN       UINT32            Socket,
311      OUT   CONST VOID        **CpuServices,
312   IN       AMD_CONFIG_PARAMS *StdHeader
313   )
314 {
315   CPU_LOGICAL_ID CpuFamilyRevision;
316
317   GetLogicalIdOfSocket (Socket, &CpuFamilyRevision, StdHeader);
318   GetFeatureServicesFromLogicalId (FamilyTable, &CpuFamilyRevision, CpuServices, StdHeader);
319 }
320
321
322 /*---------------------------------------------------------------------------------------*/
323 /**
324  *
325  *  Retrieves a pointer to the executing core's family specific services structure.
326  *
327  *  @param[out]     FunctionTable      The Processor's Family Specific services.
328  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services.
329  *
330  */
331 VOID
332 GetCpuServicesOfCurrentCore (
333      OUT   CONST CPU_SPECIFIC_SERVICES **FunctionTable,
334   IN       AMD_CONFIG_PARAMS *StdHeader
335   )
336 {
337   GetFeatureServicesOfCurrentCore (&CpuSupportedFamiliesTable,
338                                    (CONST VOID **) FunctionTable,
339                                    StdHeader);
340   if (*FunctionTable == NULL) {
341     *FunctionTable = &cpuNullServices;
342   }
343 }
344
345 /*---------------------------------------------------------------------------------------*/
346 /**
347  *
348  *  Retrieves a pointer to the family specific services structure for a processor
349  *  with the given logical ID.
350  *
351  *  @param[in]      FamilyTable        The table to search in.
352  *  @param[out]     CpuServices        The Processor's Family Specific services.
353  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services.
354  *
355  */
356 VOID
357 GetFeatureServicesOfCurrentCore (
358   IN       CPU_FAMILY_SUPPORT_TABLE *FamilyTable,
359      OUT   CONST VOID        **CpuServices,
360   IN       AMD_CONFIG_PARAMS *StdHeader
361   )
362 {
363   CPU_LOGICAL_ID CpuFamilyRevision;
364
365   GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader);
366   GetFeatureServicesFromLogicalId (FamilyTable, &CpuFamilyRevision, CpuServices, StdHeader);
367 }
368
369
370 /*---------------------------------------------------------------------------------------*/
371 /**
372  *
373  *  Retrieves a pointer to the family specific services structure for a processor
374  *  with the given logical ID.
375  *
376  *  @param[in]      LogicalId          The Processor's logical ID.
377  *  @param[out]     FunctionTable      The Processor's Family Specific services.
378  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services.
379  *
380  */
381 VOID
382 GetCpuServicesFromLogicalId (
383   IN       CPU_LOGICAL_ID *LogicalId,
384      OUT   CONST CPU_SPECIFIC_SERVICES **FunctionTable,
385   IN       AMD_CONFIG_PARAMS *StdHeader
386   )
387 {
388   GetFeatureServicesFromLogicalId (&CpuSupportedFamiliesTable,
389                                    LogicalId,
390                                    (CONST VOID **) FunctionTable,
391                                    StdHeader);
392   if (*FunctionTable == NULL) {
393     *FunctionTable = &cpuNullServices;
394   }
395 }
396
397 /*---------------------------------------------------------------------------------------*/
398 /**
399  *
400  *  Retrieves a pointer to the family specific services structure for a processor
401  *  with the given logical ID.
402  *
403  *  @param[in]      FamilyTable        The table to search in.
404  *  @param[in]      LogicalId          The Processor's logical ID.
405  *  @param[out]     CpuServices        The Processor's Family Specific services.
406  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services.
407  *
408  */
409 VOID
410 GetFeatureServicesFromLogicalId (
411   IN       CPU_FAMILY_SUPPORT_TABLE *FamilyTable,
412   IN       CPU_LOGICAL_ID    *LogicalId,
413      OUT   CONST VOID        **CpuServices,
414   IN       AMD_CONFIG_PARAMS *StdHeader
415   )
416 {
417   GetCpuServices (FamilyTable, &LogicalId->Family, CpuServices, StdHeader);
418 }
419
420
421 /*---------------------------------------------------------------------------------------*/
422 /**
423  *
424  *  Finds a family match in the given table, and returns the pointer to the
425  *  appropriate table.  If no match is found in the table, NULL will be returned.
426  *
427  *  @param[in]      FamilyTable        The table to search in.
428  *  @param[in]      MatchData          Family data that must match.
429  *  @param[out]     CpuServices        The Processor's Family Specific services.
430  *  @param[in]      StdHeader          Handle of Header for calling lib functions and services.
431  *
432  */
433 VOID
434 STATIC
435 GetCpuServices (
436   IN       CPU_FAMILY_SUPPORT_TABLE *FamilyTable,
437   IN       UINT64            *MatchData,
438      OUT   CONST VOID        **CpuServices,
439   IN       AMD_CONFIG_PARAMS *StdHeader
440   )
441 {
442   BOOLEAN IsFamily;
443   UINT8   i;
444   UINT8   NumberOfFamiliesSupported;
445   CONST CPU_SPECIFIC_SERVICES_XLAT *ImageSupportedFamiliesPtr;
446
447   ImageSupportedFamiliesPtr = FamilyTable->FamilyTable;
448   NumberOfFamiliesSupported = FamilyTable->Elements;
449   IsFamily = FALSE;
450   for (i = 0; i < NumberOfFamiliesSupported; i++) {
451     if ((ImageSupportedFamiliesPtr[i].Family & *MatchData) != 0) {
452       IsFamily = TRUE;
453       break;
454     }
455   }
456   if (IsFamily) {
457     *CpuServices = ImageSupportedFamiliesPtr[i].TablePtr;
458   } else {
459     *CpuServices = NULL;
460   }
461 }
462
463
464 /*---------------------------------------------------------------------------------------*/
465 /**
466  *  Used to stub out various family specific tables of information.
467  *
468  *  @param[in]      FamilySpecificServices  The current Family Specific Services.
469  *  @param[in]      Empty                   NULL, to indicate no data.
470  *  @param[out]     NumberOfElements        Zero, to indicate no data.
471  *  @param[in]      StdHeader               Handle of Header for calling lib functions and services.
472  *
473  */
474 VOID
475 GetEmptyArray (
476   IN       CPU_SPECIFIC_SERVICES  *FamilySpecificServices,
477      OUT   CONST VOID **Empty,
478      OUT   UINT8 *NumberOfElements,
479   IN       AMD_CONFIG_PARAMS *StdHeader
480   )
481 {
482   *NumberOfElements = 0;
483   *Empty = NULL;
484 }