Update AMD F14 Agesa to support Rev C0 cpus
[coreboot.git] / src / vendorcode / amd / agesa / f14 / Proc / CPU / Feature / cpuPstateTables.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD PSTATE, ACPI table related API functions.
6  *
7  * Contains code that generates the _PSS, _PCT, and other ACPI tables.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  CPU
12  * @e \$Revision: 35136 $   @e \$Date: 2010-07-16 11:29:48 +0800 (Fri, 16 Jul 2010) $
13  *
14  */
15 /*
16  *****************************************************************************
17  *
18  * Copyright (c) 2011, Advanced Micro Devices, Inc.
19  * All rights reserved.
20  * 
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.
31  * 
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.
42  * 
43  * ***************************************************************************
44  *
45  */
46
47
48 /*
49  *----------------------------------------------------------------------------
50  *                                MODULES USED
51  *
52  *----------------------------------------------------------------------------
53  */
54 #include "AGESA.h"
55 #include "amdlib.h"
56 #include "OptionPstate.h"
57 #include "cpuLateInit.h"
58 #include "cpuRegisters.h"
59 #include "cpuFamilyTranslation.h"
60 #include "GeneralServices.h"
61 #include "cpuServices.h"
62 #include "heapManager.h"
63 #include "Ids.h"
64 #include "Filecode.h"
65 #include "GeneralServices.h"
66 #include "cpuPstateTables.h"
67 #include "cpuFeatures.h"
68 #include "cpuIoCstate.h"
69 CODE_GROUP (G3_DXE)
70 RDATA_GROUP (G3_DXE)
71
72 #define FILECODE PROC_CPU_FEATURE_CPUPSTATETABLES_FILECODE
73 /*----------------------------------------------------------------------------
74  *                          DEFINITIONS AND MACROS
75  *
76  *----------------------------------------------------------------------------
77  */
78 extern OPTION_PSTATE_LATE_CONFIGURATION    OptionPstateLateConfiguration;  // global user config record
79 extern CPU_FAMILY_SUPPORT_TABLE            PstateFamilyServiceTable;
80 extern CPU_FAMILY_SUPPORT_TABLE            IoCstateFamilyServiceTable;
81
82 STATIC ACPI_TABLE_HEADER  ROMDATA CpuSsdtHdrStruct =
83 {
84   {'S','S','D','T'},
85   0,
86   1,
87   0,
88   {'A','M','D',' ',' ',' '},
89   {'P','O','W','E','R','N','O','W'},
90   1,
91   {'A','M','D',' '},
92   1
93 };
94
95
96 /*----------------------------------------------------------------------------
97  *                           TYPEDEFS AND STRUCTURES
98  *
99  *----------------------------------------------------------------------------
100  */
101
102 /*----------------------------------------------------------------------------
103  *                        PROTOTYPES OF LOCAL FUNCTIONS
104  *
105  *----------------------------------------------------------------------------
106  */
107
108 UINT32
109 CalAcpiTablesSize (
110   IN       S_CPU_AMD_PSTATE       *AmdPstatePtr,
111   IN       PLATFORM_CONFIGURATION *PlatformConfig,
112   IN       AMD_CONFIG_PARAMS      *StdHeader
113   );
114
115 AGESA_STATUS
116 GenerateSsdtStub (
117   IN       AMD_CONFIG_PARAMS      *StdHeader,
118   IN       PLATFORM_CONFIGURATION *PlatformConfig,
119   IN OUT   VOID                   **SsdtPtr
120   );
121
122 UINT32
123 CreateAcpiTablesStub (
124   IN       PLATFORM_CONFIGURATION *PlatformConfig,
125   IN       PSTATE_LEVELING        *PStateLevelingBuffer,
126   IN OUT   VOID                   **SsdtPtr,
127   IN       UINT8                  LocalApicId,
128   IN       AMD_CONFIG_PARAMS      *StdHeader
129   );
130
131 UINT32
132 CreatePStateAcpiTables (
133   IN       PLATFORM_CONFIGURATION *PlatformConfig,
134   IN       PSTATE_LEVELING        *PStateLevelingBuffer,
135   IN OUT   VOID                   **SsdtPtr,
136   IN       UINT8                  LocalApicId,
137   IN       AMD_CONFIG_PARAMS      *StdHeader
138   );
139
140 UINT32
141 CreateCStateAcpiTables (
142   IN       PLATFORM_CONFIGURATION *PlatformConfig,
143   IN       PSTATE_LEVELING        *PStateLevelingBuffer,
144   IN OUT   VOID                   **SsdtPtr,
145   IN       UINT8                  LocalApicId,
146   IN       AMD_CONFIG_PARAMS      *StdHeader
147   );
148
149 /**
150  *---------------------------------------------------------------------------------------
151  *
152  *  CalAcpiTablesSize
153  *
154  *  Description:
155  *    This function will calculate the size of ACPI PState tables
156  *
157  *  Parameters:
158  *    @param[in]     *AmdPstatePtr
159  *    @param[in]     *PlatformConfig
160  *    @param[in]     *StdHeader
161  *
162  *    @retval      UINT32
163  *
164  *---------------------------------------------------------------------------------------
165  */
166 UINT32
167 CalAcpiTablesSize (
168   IN       S_CPU_AMD_PSTATE       *AmdPstatePtr,
169   IN       PLATFORM_CONFIGURATION *PlatformConfig,
170   IN       AMD_CONFIG_PARAMS      *StdHeader
171   )
172 {
173   UINT32                    ScopeSize;
174   UINT32                    CoreCount;
175   UINT32                    SocketCount;
176   UINT32                    MaxCoreNumberInCurrentSocket;
177   UINT32                    MaxSocketNumberInSystem;
178   UINT32                    MaxPstateNumberInCurrentCore;
179   UINT32                    CstateAcpiObjSize;
180   PSTATE_LEVELING           *PStateLevelingBufferStructPtr;
181   IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices;
182
183   ScopeSize = sizeof (ACPI_TABLE_HEADER);
184   CstateAcpiObjSize = 0;
185   IoCstateFamilyServices = NULL;
186
187   PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc;
188   MaxSocketNumberInSystem = AmdPstatePtr->TotalSocketInSystem;
189
190   if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) {
191     GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (const VOID **)&IoCstateFamilyServices, StdHeader);
192     // If we're supporting multiple families, only proceed when IO Cstate family services are available
193     if (IoCstateFamilyServices != NULL) {
194       CstateAcpiObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader);
195     }
196   }
197
198   for (SocketCount = 0; SocketCount < MaxSocketNumberInSystem; SocketCount++) {
199     MaxCoreNumberInCurrentSocket = PStateLevelingBufferStructPtr->TotalCoresInNode;
200     for (CoreCount = 0; CoreCount < MaxCoreNumberInCurrentSocket; CoreCount++) {
201       MaxPstateNumberInCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue + 1;
202
203       ScopeSize += (SCOPE_STRUCT_SIZE - 1); // Scope size per core
204       ScopeSize += CstateAcpiObjSize;       // C-State ACPI objects size per core
205
206       // Add P-State ACPI Objects size per core
207       if ((PStateLevelingBufferStructPtr[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) {
208         ScopeSize += (PCT_STRUCT_SIZE +
209                      PSS_HEADER_STRUCT_SIZE +
210                      (MaxPstateNumberInCurrentCore * PSS_BODY_STRUCT_SIZE) +
211                      XPSS_HEADER_STRUCT_SIZE +
212                      (MaxPstateNumberInCurrentCore * XPSS_BODY_STRUCT_SIZE) +
213                      PSD_HEADER_STRUCT_SIZE +
214                      PSD_BODY_STRUCT_SIZE +
215                      PPC_HEADER_BODY_STRUCT_SIZE);
216       }
217     }
218     ScopeSize += MaxCoreNumberInCurrentSocket;
219     PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
220   }
221   AmdPstatePtr->SizeOfBytes = ScopeSize;
222
223   return ScopeSize;
224 }
225
226 /**--------------------------------------------------------------------------------------
227  *
228  *  GenerateSsdtStub
229  *
230  *  Description:
231  *     This is the default routine for use when both PState and CState option is NOT
232  *     requested. The option install process will create and fill the transfer vector
233  *     with the address of the proper routine (Main or Stub). The link optimizer will
234  *     strip out of the .DLL the routine that is not used.
235  *
236  *  Parameters:
237  *    @param[in]       StdHeader          Handle to config for library and services
238  *    @param[in]       PlatformConfig     Contains the power cap parameter
239  *    @param[in,out]   SsdtPtr            ACPI SSDT table pointer
240  *
241  *    @retval          AGESA_STATUS
242  *
243  *---------------------------------------------------------------------------------------
244  **/
245 AGESA_STATUS
246 GenerateSsdtStub (
247   IN       AMD_CONFIG_PARAMS      *StdHeader,
248   IN       PLATFORM_CONFIGURATION *PlatformConfig,
249   IN OUT   VOID                   **SsdtPtr
250   )
251 {
252   return  AGESA_UNSUPPORTED;
253 }
254
255 /**
256  *---------------------------------------------------------------------------------------
257  *
258  *  GenerateSsdt
259  *
260  *  Description:
261  *    This function will populate the SSDT with ACPI P-States and C-States Objects, whenever
262  *    necessary
263  *    This function should be called only from BSP
264  *
265  *  Parameters:
266  *    @param[in]       StdHeader          Handle to config for library and services
267  *    @param[in]       PlatformConfig     Contains the power cap parameter
268  *    @param[in,out]   SsdtPtr            ACPI SSDT pointer
269  *
270  *    @retval          AGESA_STATUS
271  *
272  *---------------------------------------------------------------------------------------
273  */
274 AGESA_STATUS
275 GenerateSsdt (
276   IN       AMD_CONFIG_PARAMS      *StdHeader,
277   IN       PLATFORM_CONFIGURATION *PlatformConfig,
278   IN OUT   VOID                   **SsdtPtr
279   )
280 {
281   UINT32                 i;
282   UINT32                 j;
283   UINT32                 TempVar8_a;
284   UINT32                 CurrSize;
285   UINT32                 TempVar_a;
286   UINT32                 TempVar_b;
287   UINT32                 ScopeSize;
288   UINT32                 CoreCount;
289   UINT32                 SocketCount;
290   UINT32                 MaxCorePerNode;
291   UINT8                  LocalApicId;
292   UINT8                  *IntermediatePtr;
293   AGESA_STATUS           AgesaStatus;
294   LOCATE_HEAP_PTR        LocateHeapParams;
295   ALLOCATE_HEAP_PARAMS   AllocateHeapParams;
296   S_CPU_AMD_PSTATE       *AmdPstatePtr;
297   PSTATE_LEVELING        *PStateLevelingBufferStructPtr;
298   SCOPE                  *ScopeAcpiTablesStructPtr;
299   SCOPE                  *ScopeAcpiTablesStructPtrTemp;
300
301   AGESA_TESTPOINT (TpProcCpuEntryPstate, StdHeader);
302
303   ASSERT (IsBsp (StdHeader, &AgesaStatus));
304
305   // If P-State and C-State ACPI tables do not need to be generated, exit this routine
306   if ((!PlatformConfig->UserOptionPState) && (!IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader))) {
307     AgesaStatus = AGESA_UNSUPPORTED;
308     return AgesaStatus;
309   }
310
311   // Initialize data variables
312   ScopeSize   = 0;
313   CoreCount   = 0;
314   LocalApicId = 0;
315   CurrSize    = 0;
316
317   // Locate P-State data buffer
318   LocateHeapParams.BufferHandle = AMD_PSTATE_DATA_BUFFER_HANDLE;
319   AGESA_TESTPOINT (TpProcCpuBeforeLocateSsdtBuffer, StdHeader);
320   if (HeapLocateBuffer (&LocateHeapParams, StdHeader) != AGESA_SUCCESS) {
321     return AGESA_ERROR;
322   }
323   AGESA_TESTPOINT (TpProcCpuAfterLocateSsdtBuffer, StdHeader);
324
325   AmdPstatePtr = (S_CPU_AMD_PSTATE *) LocateHeapParams.BufferPtr;
326   PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc;
327
328   // Allocate rough buffer for AcpiTable, if SsdtPtr is NULL
329   if (*SsdtPtr == NULL) {
330     //Do not know the actual size.. pre-calculate it.
331     AllocateHeapParams.RequestedBufferSize = CalAcpiTablesSize (AmdPstatePtr, PlatformConfig, StdHeader);
332     AllocateHeapParams.BufferHandle = AMD_PSTATE_ACPI_BUFFER_HANDLE;
333     AllocateHeapParams.Persist = HEAP_SYSTEM_MEM;
334
335     AGESA_TESTPOINT (TpProcCpuBeforeAllocateSsdtBuffer, StdHeader);
336     if (HeapAllocateBuffer (&AllocateHeapParams, StdHeader) != AGESA_SUCCESS) {
337       return AGESA_ERROR;
338     }
339     AGESA_TESTPOINT (TpProcCpuAfterAllocateSsdtBuffer, StdHeader);
340     *SsdtPtr = AllocateHeapParams.BufferPtr;
341   }
342
343   IDS_HDT_CONSOLE (CPU_TRACE, "  SSDT is created\n");
344
345   // Copy SSDT header into allocated buffer
346   LibAmdMemCopy (*SsdtPtr, (VOID *) &CpuSsdtHdrStruct, (UINTN) (sizeof (ACPI_TABLE_HEADER)), StdHeader);
347   IntermediatePtr = (UINT8 *) *SsdtPtr;
348   ScopeAcpiTablesStructPtr = (SCOPE *) &IntermediatePtr[sizeof (ACPI_TABLE_HEADER)];
349
350   SocketCount = AmdPstatePtr->TotalSocketInSystem;
351
352   // Generate name scope and ACPI objects for every core in the system
353   for (i = 0; i < SocketCount; i++) {
354     MaxCorePerNode = PStateLevelingBufferStructPtr->TotalCoresInNode;
355     for (j = 0; j < MaxCorePerNode; j++) {
356       CoreCount++;
357       // Set Name Scope for CPU0, 1, 2, ..... n
358       // CPU0 to CPUn will name  as  C000 to Cnnn
359       // -----------------------------------------
360       ScopeAcpiTablesStructPtr->ScopeOpcode      = SCOPE_OPCODE;
361       // This value will be filled at the end of this function
362       // Since at this time, we don't know how many  Pstates we
363       // would have
364       ScopeAcpiTablesStructPtr->ScopeLength      = 0;
365       ScopeAcpiTablesStructPtr->ScopeValue1      = SCOPE_VALUE1;
366       ScopeAcpiTablesStructPtr->ScopeValue2      = SCOPE_VALUE2;
367       ScopeAcpiTablesStructPtr->ScopeNamePt1a__  = SCOPE_NAME__;
368       if (PlatformConfig->ProcessorScopeInSb) {
369         ScopeAcpiTablesStructPtr->ScopeNamePt1a_P  = SCOPE_NAME_S;
370         ScopeAcpiTablesStructPtr->ScopeNamePt1a_R  = SCOPE_NAME_B;
371       } else {
372         ScopeAcpiTablesStructPtr->ScopeNamePt1a_P  = SCOPE_NAME_P;
373         ScopeAcpiTablesStructPtr->ScopeNamePt1a_R  = SCOPE_NAME_R;
374       }
375       ScopeAcpiTablesStructPtr->ScopeNamePt1b__  = SCOPE_NAME__;
376       ASSERT ((PlatformConfig->ProcessorScopeName0 >= 'A') && (PlatformConfig->ProcessorScopeName0 <= 'Z'))
377       ASSERT (((PlatformConfig->ProcessorScopeName1 >= 'A') && (PlatformConfig->ProcessorScopeName1 <= 'Z')) || \
378               ((PlatformConfig->ProcessorScopeName1 >= '0') && (PlatformConfig->ProcessorScopeName1 <= '9')) || \
379               (PlatformConfig->ProcessorScopeName1 == '_'))
380
381       ScopeAcpiTablesStructPtr->ScopeNamePt2a_C  = PlatformConfig->ProcessorScopeName0;
382       ScopeAcpiTablesStructPtr->ScopeNamePt2a_P  = PlatformConfig->ProcessorScopeName1;
383
384       TempVar8_a = ((CoreCount - 1) >> 4) & 0x0F;
385       ScopeAcpiTablesStructPtr->ScopeNamePt2a_U  = (UINT8) (SCOPE_NAME_0 + TempVar8_a);
386
387       TempVar8_a = (CoreCount - 1) & 0x0F;
388       if (TempVar8_a < 0xA) {
389         ScopeAcpiTablesStructPtr->ScopeNamePt2a_0  = (UINT8) (SCOPE_NAME_0 + TempVar8_a);
390       } else {
391         ScopeAcpiTablesStructPtr->ScopeNamePt2a_0  = (UINT8) (SCOPE_NAME_A + TempVar8_a - 0xA);
392       }
393       // Increment and typecast the pointer
394       ScopeAcpiTablesStructPtrTemp = ScopeAcpiTablesStructPtr;
395       ScopeAcpiTablesStructPtrTemp++;
396
397       // Get the Local Apic Id for each core
398       LocalApicId = PStateLevelingBufferStructPtr->PStateCoreStruct[0].LocalApicId + (UINT8) j;
399
400       // Create P-State ACPI Objects
401       CurrSize += ((*(OptionPstateLateConfiguration.PstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader));
402
403       // Create C-State ACPI Objects
404       CurrSize += ((*(OptionPstateLateConfiguration.CstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader));
405
406       // Now update the SCOPE Length field
407       {
408         CurrSize += (SCOPE_STRUCT_SIZE - 1);
409         ScopeSize += CurrSize;
410
411         TempVar_b = ((CurrSize << 4) & 0x0000FF00);
412         TempVar_b |= ((CurrSize & 0x0000000F) | 0x00000040);
413         TempVar_a = TempVar_b;
414         ScopeAcpiTablesStructPtr->ScopeLength = (UINT16) TempVar_a;
415         CurrSize = 0;
416       }
417
418       ScopeAcpiTablesStructPtr = ScopeAcpiTablesStructPtrTemp;
419     }
420     //Calculate next node buffer address
421     PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
422   }
423   //Update SSDT header Checksum
424   ((ACPI_TABLE_HEADER *) *SsdtPtr)->TableLength = (ScopeSize + CoreCount + sizeof (ACPI_TABLE_HEADER));
425   ChecksumAcpiTable ((ACPI_TABLE_HEADER *) *SsdtPtr, StdHeader);
426
427   return AGESA_SUCCESS;
428 }
429
430 /**--------------------------------------------------------------------------------------
431  *
432  *  CreateAcpiTablesStub
433  *
434  *  Description:
435  *     This is the default routine for use when the P-State or C-State option is NOT
436  *     requested. The option install process will create and fill the transfer vector
437  *     with the address of the proper routine (Main or Stub). The link optimizer will
438  *     strip out of the .DLL the routine that is not used.
439  *
440  *  Parameters:
441  *    @param[in]     PlatformConfig       Platform operational characteristics; power cap
442  *    @param[in]     PStateLevelingBuffer Buffer that contains P-State Leveling information
443  *    @param[in,out] SsdtPtr              ACPI SSDT table pointer
444  *    @param[in]     LocalApicId          Local Apic Id
445  *    @param[in]     StdHeader            Handle to config for library and services
446  *
447  *    @retval        Size of generated ACPI objects
448  *
449  *---------------------------------------------------------------------------------------
450  **/
451 UINT32
452 CreateAcpiTablesStub (
453   IN       PLATFORM_CONFIGURATION *PlatformConfig,
454   IN       PSTATE_LEVELING        *PStateLevelingBuffer,
455   IN OUT   VOID                   **SsdtPtr,
456   IN       UINT8                  LocalApicId,
457   IN       AMD_CONFIG_PARAMS      *StdHeader
458   )
459 {
460   return  0;
461 }
462
463
464 /**--------------------------------------------------------------------------------------
465  *
466  *  CreatePStateAcpiTables
467  *
468  *  Description:
469  *     This is the common routine for creating ACPI P-State objects
470  *
471  *  Parameters:
472  *    @param[in]     PlatformConfig       Platform operational characteristics; power cap
473  *    @param[in]     PStateLevelingBuffer Buffer that contains P-State Leveling information
474  *    @param[in,out] SsdtPtr              ACPI SSDT table pointer
475  *    @param[in]     LocalApicId          Local Apic Id
476  *    @param[in]     StdHeader            Handle to config for library and services
477  *
478  *    @retval          Size of generated ACPI P-States objects
479  *
480  *---------------------------------------------------------------------------------------
481  **/
482 UINT32
483 CreatePStateAcpiTables (
484   IN       PLATFORM_CONFIGURATION *PlatformConfig,
485   IN       PSTATE_LEVELING        *PStateLevelingBuffer,
486   IN OUT   VOID                   **SsdtPtr,
487   IN       UINT8                  LocalApicId,
488   IN       AMD_CONFIG_PARAMS      *StdHeader
489   )
490 {
491   UINT8                      PstateCapLevelSupport;
492   UINT8                      PStateMaxValueOnCurrentCore;
493   BOOLEAN                    PstateCapEnable;
494   BOOLEAN                    PstateCapLevelSupportDetermined;
495   BOOLEAN                    IsPsdDependent;
496   UINT32                     k;
497   UINT32                     TempVar_a;
498   UINT32                     TempVar_b;
499   UINT32                     TempVar_c;
500   UINT32                     PstateCapInputMilliWatts;
501   UINT32                     CurrSize;
502   UINT32                     PstateCount;
503   UINT32                     CoreCount1;
504   UINT32                     TransAndBusMastLatency;
505   AGESA_STATUS               IgnoredStatus;
506   PCI_ADDR                   PciAddress;
507   PCT_HEADER_BODY            *pPctAcpiTables;
508   PSS_HEADER                 *pPssHeaderAcpiTables;
509   PSS_BODY                   *pPssBodyAcpiTables;
510   XPSS_HEADER                *pXpssHeaderAcpiTables;
511   XPSS_BODY                  *pXpssBodyAcpiTables;
512   PSD_HEADER                 *pPsdHeaderAcpiTables;
513   PSD_BODY                   *pPsdBodyAcpiTables;
514   PPC_HEADER_BODY            *pPpcAcpiTables;
515   PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
516
517   CurrSize = 0;
518   PstateCount = 0;
519   PstateCapEnable = FALSE;
520   PstateCapLevelSupport = DEFAULT_PERF_PRESENT_CAP;
521   PstateCapLevelSupportDetermined = TRUE;
522   PstateCapInputMilliWatts = PlatformConfig->PowerCeiling;
523   IsPsdDependent = !(PlatformConfig->ForcePstateIndependent);
524   TransAndBusMastLatency = 0;
525
526   if ((PStateLevelingBuffer[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) {
527     pPctAcpiTables = (PCT_HEADER_BODY *) *SsdtPtr;
528
529     //Check Pstate Capability
530     if (PstateCapInputMilliWatts != 0) {
531       PstateCapEnable = TRUE;
532       PstateCapLevelSupportDetermined = FALSE;
533     }
534
535     PStateMaxValueOnCurrentCore = PStateLevelingBuffer->PStateCoreStruct[0].PStateMaxValue;
536     if (OptionPstateLateConfiguration.CfgPstatePct) {
537       // Set _PCT Table
538       // --------------
539       pPctAcpiTables->NameOpcode              = NAME_OPCODE;
540       pPctAcpiTables->PctName_a__             = PCT_NAME__;
541       pPctAcpiTables->PctName_a_P             = PCT_NAME_P;
542       pPctAcpiTables->PctName_a_C             = PCT_NAME_C;
543       pPctAcpiTables->PctName_a_T             = PCT_NAME_T;
544       pPctAcpiTables->Value1                  = PCT_VALUE1;
545       pPctAcpiTables->Value2                  = PCT_VALUE2;
546       pPctAcpiTables->Value3                  = PCT_VALUE3;
547       pPctAcpiTables->GenericRegDescription1  = GENERIC_REG_DESCRIPTION;
548       pPctAcpiTables->Length1                 = PCT_LENGTH;
549       pPctAcpiTables->AddressSpaceId1         = PCT_ADDRESS_SPACE_ID;
550       pPctAcpiTables->RegisterBitWidth1       = PCT_REGISTER_BIT_WIDTH;
551       pPctAcpiTables->RegisterBitOffset1      = PCT_REGISTER_BIT_OFFSET;
552       pPctAcpiTables->Reserved1               = PCT_RESERVED;
553       pPctAcpiTables->ControlRegAddressLo     = PCT_CONTROL_REG_LO;
554       pPctAcpiTables->ControlRegAddressHi     = PCT_CONTROL_REG_HI;
555       pPctAcpiTables->Value4                  = PCT_VALUE4;
556       pPctAcpiTables->Value5                  = PCT_VALUE5;
557       pPctAcpiTables->GenericRegDescription2  = GENERIC_REG_DESCRIPTION;
558       pPctAcpiTables->Length2                 = PCT_LENGTH;
559       pPctAcpiTables->AddressSpaceId2         = PCT_ADDRESS_SPACE_ID;
560       pPctAcpiTables->RegisterBitWidth2       = PCT_REGISTER_BIT_WIDTH;
561       pPctAcpiTables->RegisterBitOffset2      = PCT_REGISTER_BIT_OFFSET;
562       pPctAcpiTables->Reserved2               = PCT_RESERVED;
563       pPctAcpiTables->StatusRegAddressLo      = PCT_STATUS_REG_LO;
564       pPctAcpiTables->StatusRegAddressHi      = PCT_STATUS_REG_HI;
565       pPctAcpiTables->Value6                  = PCT_VALUE6;
566
567       // Increment and then typecast the pointer
568       pPctAcpiTables++;
569       CurrSize += PCT_STRUCT_SIZE;
570
571       *SsdtPtr = pPctAcpiTables;
572     } // end of OptionPstateLateConfiguration.CfgPstatePct
573
574     pPssHeaderAcpiTables = (PSS_HEADER *) pPctAcpiTables;
575     pPssBodyAcpiTables   = (PSS_BODY *)   pPctAcpiTables;
576     if (OptionPstateLateConfiguration.CfgPstatePss) {
577       // Set _PSS Header
578       // Note: Set pssLength and numOfItemsInPss later
579       //---------------------------------------------------
580       pPssHeaderAcpiTables->NameOpcode      = NAME_OPCODE;
581       pPssHeaderAcpiTables->PssName_a__     = PSS_NAME__;
582       pPssHeaderAcpiTables->PssName_a_P     = PSS_NAME_P;
583       pPssHeaderAcpiTables->PssName_a_S     = PSS_NAME_S;
584       pPssHeaderAcpiTables->PssName_b_S     = PSS_NAME_S;
585       pPssHeaderAcpiTables->PkgOpcode       = PACKAGE_OPCODE;
586
587       pPssHeaderAcpiTables++;
588       pPssBodyAcpiTables = (PSS_BODY *) pPssHeaderAcpiTables;
589       // Restore the pPssHeaderAcpiTables
590       pPssHeaderAcpiTables--;
591
592       // Set _PSS Body
593       //---------------
594       PstateCount = 0;
595
596       // Calculate PCI address for socket only
597       GetPciAddress (StdHeader, (UINT32) PStateLevelingBuffer->SocketNumber, 0, &PciAddress, &IgnoredStatus);
598       TransAndBusMastLatency = 0;
599       GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (const VOID **)&FamilyServices, StdHeader);
600       ASSERT (FamilyServices != NULL)
601       FamilyServices->GetPstateLatency (  FamilyServices,
602                                           PStateLevelingBuffer,
603                                           &PciAddress,
604                                           &TransAndBusMastLatency,
605                                           StdHeader);
606
607       for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) {
608         if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
609           pPssBodyAcpiTables->PkgOpcode           = PACKAGE_OPCODE;
610           pPssBodyAcpiTables->PkgLength           = PSS_PKG_LENGTH;
611           pPssBodyAcpiTables->NumOfElements       = PSS_NUM_OF_ELEMENTS;
612           pPssBodyAcpiTables->DwordPrefixOpcode1  = DWORD_PREFIX_OPCODE;
613           pPssBodyAcpiTables->Frequency           =
614           PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq;
615           pPssBodyAcpiTables->DwordPrefixOpcode2  = DWORD_PREFIX_OPCODE;
616           pPssBodyAcpiTables->Power               =
617           PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power;
618
619           if (PstateCapEnable && (!PstateCapLevelSupportDetermined) && (PstateCapInputMilliWatts >= pPssBodyAcpiTables->Power)) {
620             PstateCapLevelSupport = (UINT8) PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
621             PstateCapLevelSupportDetermined = TRUE;
622           }
623
624           pPssBodyAcpiTables->DwordPrefixOpcode3  = DWORD_PREFIX_OPCODE;
625           pPssBodyAcpiTables->TransitionLatency   = TransAndBusMastLatency;
626           pPssBodyAcpiTables->DwordPrefixOpcode4  = DWORD_PREFIX_OPCODE;
627           pPssBodyAcpiTables->BusMasterLatency    = TransAndBusMastLatency;
628           pPssBodyAcpiTables->DwordPrefixOpcode5  = DWORD_PREFIX_OPCODE;
629           pPssBodyAcpiTables->Control             =
630           PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
631           pPssBodyAcpiTables->DwordPrefixOpcode6  = DWORD_PREFIX_OPCODE;
632           pPssBodyAcpiTables->Status              =
633           PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
634
635           pPssBodyAcpiTables++;
636           PstateCount++;
637         }
638       } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
639
640       if (PstateCapEnable && (!PstateCapLevelSupportDetermined)) {
641         PstateCapLevelSupport = PStateMaxValueOnCurrentCore;
642       }
643
644       // Set _PSS Header again
645       // Now Set pssLength and numOfItemsInPss
646       //---------------------------------------
647       TempVar_a = (PstateCount * PSS_BODY_STRUCT_SIZE) + 3;
648       TempVar_b = TempVar_a;
649       TempVar_c = ((TempVar_b << 4) & 0x0000FF00);
650       TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040);
651       TempVar_a = (UINT16) TempVar_c;
652
653       pPssHeaderAcpiTables->PssLength = (UINT16) TempVar_a;
654       pPssHeaderAcpiTables->NumOfItemsInPss = (UINT8) PstateCount;
655       CurrSize += (PSS_HEADER_STRUCT_SIZE + (PstateCount * PSS_BODY_STRUCT_SIZE));
656
657       *SsdtPtr = pPssBodyAcpiTables;
658     } // end of PSS Body if OptionPstateLateConfiguration.CfgPstatePss
659
660     // Set XPSS Table
661     //---------------
662     // Typecast the pointer
663     pXpssHeaderAcpiTables = (XPSS_HEADER *) pPssBodyAcpiTables;
664     pXpssBodyAcpiTables   = (XPSS_BODY *)   pPssBodyAcpiTables;
665     if (OptionPstateLateConfiguration.CfgPstateXpss) {
666       // Set XPSS Header
667       // Note: Set the pssLength and numOfItemsInPss later
668       //---------------------------------------------------
669       pXpssHeaderAcpiTables->NameOpcode       = NAME_OPCODE;
670       pXpssHeaderAcpiTables->XpssName_a_X     = PSS_NAME_X;
671       pXpssHeaderAcpiTables->XpssName_a_P     = PSS_NAME_P;
672       pXpssHeaderAcpiTables->XpssName_a_S     = PSS_NAME_S;
673       pXpssHeaderAcpiTables->XpssName_b_S     = PSS_NAME_S;
674       pXpssHeaderAcpiTables->PkgOpcode        = PACKAGE_OPCODE;
675
676       // Increment and then typecast the pointer
677       pXpssHeaderAcpiTables++;
678       pXpssBodyAcpiTables = (XPSS_BODY *) pXpssHeaderAcpiTables;
679       // Restore the pXpssHeaderAcpiTables
680       pXpssHeaderAcpiTables--;
681
682       // Set XPSS Body
683       //---------------
684       for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) {
685         if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
686           pXpssBodyAcpiTables->PkgOpcode          = PACKAGE_OPCODE;
687           pXpssBodyAcpiTables->PkgLength          = XPSS_PKG_LENGTH;
688           pXpssBodyAcpiTables->NumOfElements      = XPSS_NUM_OF_ELEMENTS;
689           pXpssBodyAcpiTables->XpssValueTbd       = 04;
690           pXpssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
691           pXpssBodyAcpiTables->Frequency          =
692           PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq;
693           pXpssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
694           pXpssBodyAcpiTables->Power              =
695           PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power;
696           pXpssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
697           pXpssBodyAcpiTables->TransitionLatency  = TransAndBusMastLatency;
698           pXpssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE;
699           pXpssBodyAcpiTables->BusMasterLatency   = TransAndBusMastLatency;
700           pXpssBodyAcpiTables->ControlBuffer      = XPSS_ACPI_BUFFER;
701           pXpssBodyAcpiTables->ControlLo          =
702           PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
703           pXpssBodyAcpiTables->ControlHi          = 0;
704           pXpssBodyAcpiTables->StatusBuffer       = XPSS_ACPI_BUFFER;
705           pXpssBodyAcpiTables->StatusLo           =
706           PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
707           pXpssBodyAcpiTables->StatusHi           = 0;
708           pXpssBodyAcpiTables->ControlMaskBuffer  = XPSS_ACPI_BUFFER;
709           pXpssBodyAcpiTables->ControlMaskLo      = 0;
710           pXpssBodyAcpiTables->ControlMaskHi      = 0;
711           pXpssBodyAcpiTables->StatusMaskBuffer   = XPSS_ACPI_BUFFER;
712           pXpssBodyAcpiTables->StatusMaskLo       = 0;
713           pXpssBodyAcpiTables->StatusMaskHi       = 0;
714
715           pXpssBodyAcpiTables++;
716         }
717       } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
718
719       // Set XPSS Header again
720       // Now set pssLength and numOfItemsInPss
721       //---------------------------------------
722       TempVar_a = (PstateCount * XPSS_BODY_STRUCT_SIZE) + 3;
723       TempVar_b = TempVar_a;
724       TempVar_c = ((TempVar_b << 4) & 0x0000FF00);
725       TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040);
726       TempVar_a = (UINT16) TempVar_c;
727
728       pXpssHeaderAcpiTables->XpssLength = (UINT16) TempVar_a;
729       pXpssHeaderAcpiTables->NumOfItemsInXpss = (UINT8) PstateCount;
730       CurrSize += (XPSS_HEADER_STRUCT_SIZE + (PstateCount * XPSS_BODY_STRUCT_SIZE));
731
732       *SsdtPtr = pXpssBodyAcpiTables;
733     } //end of XPSS Body OptionPstateLateConfiguration.CfgPstateXpss
734
735     // Set _PSD Table
736     //---------------
737     // Typecast the pointer
738     pPsdHeaderAcpiTables = (PSD_HEADER *) pXpssBodyAcpiTables;
739     pPsdBodyAcpiTables = (PSD_BODY *)     pXpssBodyAcpiTables;
740     // Get Total Cores Per Node
741     if (GetActiveCoresInGivenSocket ((UINT32) PStateLevelingBuffer->SocketNumber, &CoreCount1, StdHeader)) {
742       GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (const VOID **)&FamilyServices, StdHeader);
743       ASSERT (FamilyServices != NULL)
744       if ((CoreCount1 != 1) && (OptionPstateLateConfiguration.CfgPstatePsd) &&
745           FamilyServices->IsPstatePsdNeeded (FamilyServices, PlatformConfig, StdHeader)) {
746         // Set _PSD Header
747         //----------------
748         pPsdHeaderAcpiTables->NameOpcode    = NAME_OPCODE;
749         pPsdHeaderAcpiTables->PkgOpcode     = PACKAGE_OPCODE;
750         pPsdHeaderAcpiTables->PsdLength     = PSD_HEADER_LENGTH;
751         pPsdHeaderAcpiTables->Value1        = PSD_VALUE1;
752         pPsdHeaderAcpiTables->PsdName_a__   = PSD_NAME__;
753         pPsdHeaderAcpiTables->PsdName_a_P   = PSD_NAME_P;
754         pPsdHeaderAcpiTables->PsdName_a_S   = PSD_NAME_S;
755         pPsdHeaderAcpiTables->PsdName_a_D   = PSD_NAME_D;
756
757         // Typecast the pointer
758         pPsdHeaderAcpiTables++;
759         CurrSize += PSD_HEADER_STRUCT_SIZE;
760         pPsdBodyAcpiTables = (PSD_BODY *) pPsdHeaderAcpiTables;
761
762         pPsdHeaderAcpiTables--;
763         // Set _PSD Body
764         //--------------
765         pPsdBodyAcpiTables->PkgOpcode           = PACKAGE_OPCODE;
766         pPsdBodyAcpiTables->PkgLength           = PSD_PKG_LENGTH;
767         pPsdBodyAcpiTables->NumOfEntries        = NUM_OF_ENTRIES;
768         pPsdBodyAcpiTables->BytePrefixOpcode1   = BYTE_PREFIX_OPCODE;
769         pPsdBodyAcpiTables->PsdNumOfEntries     = PSD_NUM_OF_ENTRIES;
770         pPsdBodyAcpiTables->BytePrefixOpcode2   = BYTE_PREFIX_OPCODE;
771         pPsdBodyAcpiTables->PsdRevision         = PSD_REVISION;
772         pPsdBodyAcpiTables->DwordPrefixOpcode1  = DWORD_PREFIX_OPCODE;
773
774         IsPsdDependent = FamilyServices->IsPstatePsdDependent (FamilyServices, PlatformConfig, StdHeader);
775
776         if (IsPsdDependent) {
777           pPsdBodyAcpiTables->DependencyDomain    = PSD_DEPENDENCY_DOMAIN;
778           pPsdBodyAcpiTables->CoordinationType    = PSD_COORDINATION_TYPE_SW_ALL;
779           pPsdBodyAcpiTables->NumOfProcessors     = CoreCount1;
780         } else {
781           switch (GetComputeUnitMapping (StdHeader)) {
782           case AllCoresMapping:
783             // All cores are in their own compute unit.
784             pPsdBodyAcpiTables->DependencyDomain    = LocalApicId;
785             pPsdBodyAcpiTables->CoordinationType    = PSD_COORDINATION_TYPE_SW_ANY;
786             pPsdBodyAcpiTables->NumOfProcessors     = PSD_NUM_OF_PROCESSORS;
787             break;
788           case EvenCoresMapping:
789             // Cores are paired in compute units.
790             pPsdBodyAcpiTables->DependencyDomain    = (LocalApicId >> 1) & PSD_DOMAIN_COMPUTE_UNIT_MASK;
791             pPsdBodyAcpiTables->CoordinationType    = PSD_COORDINATION_TYPE_HW_ALL;
792             pPsdBodyAcpiTables->NumOfProcessors     = PSD_CORE_NUM_PER_COMPUTE_UNIT;
793             break;
794           default:
795             ASSERT (FALSE);
796           }
797         }
798         pPsdBodyAcpiTables->DwordPrefixOpcode2  = DWORD_PREFIX_OPCODE;
799         pPsdBodyAcpiTables->DwordPrefixOpcode3  = DWORD_PREFIX_OPCODE;
800
801         pPsdBodyAcpiTables++;
802         *SsdtPtr = pPsdBodyAcpiTables;
803         CurrSize += PSD_BODY_STRUCT_SIZE;
804       }
805     }// end of PSD Body if (CoreCount1 != 1) || (OptionPstateLateConfiguration.CfgPstatePsd)
806     // Typecast the pointer
807
808     pPpcAcpiTables = (PPC_HEADER_BODY *) pPsdBodyAcpiTables;
809
810     // Set _PPC Table
811     //---------------
812     if (OptionPstateLateConfiguration.CfgPstatePpc) {
813       pPpcAcpiTables->NameOpcode            = NAME_OPCODE;
814       pPpcAcpiTables->PpcName_a__           = PPC_NAME__;
815       pPpcAcpiTables->PpcName_a_P           = PPC_NAME_P;
816       pPpcAcpiTables->PpcName_b_P           = PPC_NAME_P;
817       pPpcAcpiTables->PpcName_a_C           = PPC_NAME_C;
818       pPpcAcpiTables->Value1                = PPC_VALUE1;
819
820       pPpcAcpiTables->DefaultPerfPresentCap = PstateCapLevelSupport;
821       CurrSize += PPC_HEADER_BODY_STRUCT_SIZE;
822       // Increment and typecast the pointer
823       pPpcAcpiTables++;
824       *SsdtPtr =  pPpcAcpiTables;
825     }// end of OptionPstateLateConfiguration.CfgPstatePpc
826   }
827   return CurrSize;
828 }
829
830 /**--------------------------------------------------------------------------------------
831  *
832  *  CreateCStateAcpiTables
833  *
834  *  Description:
835  *     This is the common routine for creating ACPI C-State objects
836  *
837  *  Parameters:
838  *    @param[in]     PlatformConfig       Platform operational characteristics; power cap
839  *    @param[in]     PStateLevelingBuffer Buffer that contains P-State Leveling information
840  *    @param[in,out] SsdtPtr              ACPI SSDT table pointer
841  *    @param[in]     LocalApicId          Local Apic Id
842  *    @param[in]     StdHeader            Handle to config for library and services
843  *
844  *    @retval        Size of ACPI C-States objects generated
845  *
846  *---------------------------------------------------------------------------------------
847  **/
848 UINT32
849 CreateCStateAcpiTables (
850   IN       PLATFORM_CONFIGURATION *PlatformConfig,
851   IN       PSTATE_LEVELING        *PStateLevelingBuffer,
852   IN OUT   VOID                   **SsdtPtr,
853   IN       UINT8                  LocalApicId,
854   IN       AMD_CONFIG_PARAMS      *StdHeader
855   )
856 {
857   UINT32                    ObjSize;
858   IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices;
859
860   ObjSize = 0;
861
862   if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) {
863     GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (const VOID **)&IoCstateFamilyServices, StdHeader);
864     // If we're supporting multiple families, only proceed when IO Cstate family services are available
865     if (IoCstateFamilyServices != NULL) {
866       IoCstateFamilyServices->CreateAcpiCstObj (IoCstateFamilyServices, LocalApicId, SsdtPtr, StdHeader);
867       ObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader);
868     }
869   }
870   return ObjSize;
871 }