AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / Feature / cpuPstateGather.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD CPU Pstate Data Gather Function.
6  *
7  * Contains code to collect all the Pstate related information from MSRs, and PCI registers.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  CPU
12  * @e \$Revision: 56279 $   @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
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 /*
47  *----------------------------------------------------------------------------
48  *                                MODULES USED
49  *
50  *----------------------------------------------------------------------------
51  */
52 #include "AGESA.h"
53 #include "amdlib.h"
54 #include "OptionPstate.h"
55 #include "cpuRegisters.h"
56 #include "cpuServices.h"
57 #include "GeneralServices.h"
58 #include "cpuPostInit.h"
59 #include "Ids.h"
60 #include "cpuFamilyTranslation.h"
61 #include "cpuPstateTables.h"
62 #include "cpuApicUtilities.h"
63 #include "cpuFeatures.h"
64 #include "Filecode.h"
65 CODE_GROUP (G1_PEICC)
66 RDATA_GROUP (G2_PEI)
67
68 #define FILECODE PROC_CPU_FEATURE_CPUPSTATEGATHER_FILECODE
69
70 /*----------------------------------------------------------------------------
71  *                          DEFINITIONS AND MACROS
72  *
73  *----------------------------------------------------------------------------
74  */
75 extern OPTION_PSTATE_POST_CONFIGURATION    OptionPstatePostConfiguration;  // global user config record
76 extern CPU_FAMILY_SUPPORT_TABLE            PstateFamilyServiceTable;
77
78 /*----------------------------------------------------------------------------
79  *                           TYPEDEFS AND STRUCTURES
80  *
81  *----------------------------------------------------------------------------
82  */
83
84 /*----------------------------------------------------------------------------
85  *                        PROTOTYPES OF LOCAL FUNCTIONS
86  *
87  *----------------------------------------------------------------------------
88  */
89 AGESA_STATUS
90 PStateGatherStub (
91   IN       AMD_CONFIG_PARAMS *StdHeader,
92   IN OUT   S_CPU_AMD_PSTATE  *PStateStrucPtr
93   );
94
95 AGESA_STATUS
96 PStateGatherMain (
97   IN       AMD_CONFIG_PARAMS *StdHeader,
98   IN OUT   S_CPU_AMD_PSTATE  *PStateStrucPtr
99   );
100
101
102 /*----------------------------------------------------------------------------
103  *                            EXPORTED FUNCTIONS
104  *
105  *----------------------------------------------------------------------------
106  */
107 VOID
108 PStateGather (
109   IN OUT   VOID *PStateBuffer,
110   IN       AMD_CONFIG_PARAMS   *StdHeader
111   );
112
113 /**
114  *---------------------------------------------------------------------------------------
115  *
116  *  PStateGatherData
117  *
118  *  Description:
119  *    This function will gather PState information from the MSRs and fill up the
120  *    pStateBuf. This buffer will be used by the PState Leveling, and PState Table
121  *    generation code later.
122  *
123  *  Parameters:
124  *    @param[in]        *PlatformConfig
125  *    @param[in, out]   *PStateStrucPtr
126  *    @param[in]        *StdHeader
127  *
128  *    @retval      AGESA_STATUS
129  *
130  *---------------------------------------------------------------------------------------
131  **/
132 AGESA_STATUS
133 PStateGatherData (
134   IN       PLATFORM_CONFIGURATION *PlatformConfig,
135   IN OUT   S_CPU_AMD_PSTATE       *PStateStrucPtr,
136   IN       AMD_CONFIG_PARAMS      *StdHeader
137   )
138 {
139
140
141   AGESA_STATUS       AgesaStatus;
142
143   AGESA_TESTPOINT (TpProcCpuEntryPstateGather, StdHeader);
144   AgesaStatus = AGESA_SUCCESS;
145
146   // Gather data for ACPI Tables if ACPI P-States/C-States object generation is enabled.
147   if ((PlatformConfig->UserOptionPState) || (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader))) {
148     AgesaStatus = (*(OptionPstatePostConfiguration.PstateGather)) (StdHeader, PStateStrucPtr);
149     // Note: Split config struct into PEI/DXE halves. This one is PEI.
150   }
151
152   return AgesaStatus;
153 }
154
155 /**--------------------------------------------------------------------------------------
156  *
157  *  PStateGatherStub
158  *
159  *  Description:
160  *     This is the default routine for use when the PState option is NOT requested.
161  *      The option install process will create and fill the transfer vector with
162  *      the address of the proper routine (Main or Stub). The link optimizer will
163  *      strip out of the .DLL the routine that is not used.
164  *
165  *  Parameters:
166  *    @param[in]        *StdHeader
167  *    @param[in, out]   *PStateStrucPtr
168  *
169  *    @retval         AGESA_STATUS
170  *
171  *---------------------------------------------------------------------------------------
172  **/
173 AGESA_STATUS
174 PStateGatherStub (
175   IN       AMD_CONFIG_PARAMS *StdHeader,
176   IN OUT   S_CPU_AMD_PSTATE  *PStateStrucPtr
177   )
178 {
179   return  AGESA_UNSUPPORTED;
180 }
181
182 /**--------------------------------------------------------------------------------------
183  *
184  *  PStateGatherMain
185  *
186  *  Description:
187  *     This is the common routine for BSP gathering the Pstate data.
188  *
189  *  Parameters:
190  *    @param[in]        *StdHeader
191  *    @param[in, out]   *PStateStrucPtr
192  *
193  *    @retval         AGESA_STATUS
194  *
195  *---------------------------------------------------------------------------------------
196  **/
197 AGESA_STATUS
198 PStateGatherMain (
199   IN       AMD_CONFIG_PARAMS *StdHeader,
200   IN OUT   S_CPU_AMD_PSTATE  *PStateStrucPtr
201   )
202 {
203   AP_TASK                 TaskPtr;
204   UINT32                  BscSocket;
205   UINT32                  Ignored;
206   UINT32                  PopulatedSockets;
207   UINT32                  NumberOfSockets;
208   UINT32                  Socket;
209   AGESA_STATUS            IgnoredSts;
210   PSTATE_LEVELING         *PStateBufferPtr;
211   PSTATE_CPU_FAMILY_SERVICES  *FamilyServices;
212   UINT32                  MaxState;
213   UINT8                   IgnoredByte;
214
215   ASSERT (IsBsp (StdHeader, &IgnoredSts));
216
217   FamilyServices = NULL;
218   GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
219   ASSERT (FamilyServices != NULL);
220
221   PopulatedSockets = 1;
222   PStateBufferPtr = PStateStrucPtr->PStateLevelingStruc;
223
224   NumberOfSockets = GetPlatformNumberOfSockets ();
225   IdentifyCore (StdHeader, &BscSocket, &Ignored, &Ignored, &IgnoredSts);
226
227   PStateStrucPtr->SizeOfBytes = sizeof (S_CPU_AMD_PSTATE);
228
229   MaxState = 0;
230   FamilyServices->GetPstateMaxState (FamilyServices, &MaxState, &IgnoredByte, StdHeader);
231
232   TaskPtr.FuncAddress.PfApTaskI = PStateGather;
233   //
234   // Calculate max buffer size in dwords that need to pass to ap task.
235   //
236   TaskPtr.DataTransfer.DataSizeInDwords = (UINT16) ((MaxState + 1) * (SIZE_IN_DWORDS (S_PSTATE_VALUES)));
237   TaskPtr.ExeFlags = WAIT_FOR_CORE;
238   TaskPtr.DataTransfer.DataPtr = PStateBufferPtr;
239   TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
240
241   //
242   //Get P-States and fill the PStateBufferPtr for BSP
243   //
244   ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, NULL);
245
246   //
247   //Calculate next node buffer address
248   //
249   PStateBufferPtr->SocketNumber = (UINT8) BscSocket;
250   PStateBufferPtr->PStateLevelingSizeOfBytes = (UINT16) (sizeof (PSTATE_LEVELING) + (UINT32) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
251   PStateStrucPtr->SizeOfBytes += (UINT32) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES));
252   PStateBufferPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
253   CpuGetPStateLevelStructure (&PStateBufferPtr, PStateStrucPtr, 1, StdHeader);
254   //
255   //Get CPU P-States and fill the PStateBufferPtr for each node(BSC)
256   //
257   for (Socket = 0; Socket < NumberOfSockets; Socket++) {
258     if (Socket != BscSocket) {
259       if (IsProcessorPresent (Socket, StdHeader)) {
260         PopulatedSockets++;
261         LibAmdMemFill (PStateBufferPtr, 0, sizeof (PSTATE_LEVELING), StdHeader);
262         TaskPtr.DataTransfer.DataPtr = PStateBufferPtr;
263         ApUtilRunCodeOnSocketCore ((UINT8)Socket, 0, &TaskPtr, StdHeader);
264         PStateBufferPtr->SocketNumber = (UINT8) Socket;
265         //
266         //Calculate next node buffer address
267         //
268         PStateBufferPtr->PStateLevelingSizeOfBytes = (UINT16) (sizeof (PSTATE_LEVELING) + (UINT32) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
269         PStateStrucPtr->SizeOfBytes += PStateBufferPtr->PStateLevelingSizeOfBytes;
270         PStateBufferPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
271       }
272     }
273   }
274   PStateStrucPtr->TotalSocketInSystem = PopulatedSockets;
275
276   return AGESA_SUCCESS;
277 }
278 /**--------------------------------------------------------------------------------------
279  *
280  *  PStateGather
281  *
282  *  Description:
283  *     This is the common routine run on each BSC for gathering Pstate data.
284  *
285  *  Parameters:
286  *    @param[in,out]    *PStateBuffer
287  *    @param[in]        *StdHeader
288  *
289  *    @retval         VOID
290  *
291  *---------------------------------------------------------------------------------------
292  **/
293 VOID
294 PStateGather (
295   IN OUT   VOID                *PStateBuffer,
296   IN       AMD_CONFIG_PARAMS   *StdHeader
297   )
298 {
299   UINT32                 k;
300   UINT32                 IddVal;
301   UINT32                 IddDiv;
302   UINT32                 NodeNum;
303   UINT32                 CoreNum;
304   UINT32                 TempVar_c;
305   UINT32                 TotalEnabledPStates;
306   UINT32                 SwPstate;
307   UINT8                  BoostStates;
308   PCI_ADDR               PciAddress;
309   PSTATE_LEVELING        *PStateBufferPtr;
310   BOOLEAN                PStateEnabled;
311   PSTATE_CPU_FAMILY_SERVICES  *FamilyServices;
312   UINT32                 Socket;
313   AGESA_STATUS           IgnoredSts;
314   CPUID_DATA             CpuId;
315
316   PStateBufferPtr = (PSTATE_LEVELING *) PStateBuffer;
317   TotalEnabledPStates = 0;
318   FamilyServices = NULL;
319   PStateEnabled = FALSE;
320
321   GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
322   ASSERT (FamilyServices != NULL);
323
324   //
325   /// Sockets number:  code looking at PStateBufferPtr->TotalCoresInNode
326   ///        needs to know it is Processor (or socket) core count and NOT a Node Core count.
327   GetActiveCoresInCurrentSocket (&CoreNum, StdHeader);
328   PStateBufferPtr->TotalCoresInNode = (UINT8) CoreNum;
329
330   //
331   // Assume current CoreNum always zero.(BSC)
332   //
333   GetCurrentNodeAndCore (&NodeNum, &CoreNum, StdHeader);
334
335   PStateBufferPtr->CreateAcpiTables = 1;
336
337   //
338   // We need to know the max pstate state in this socket.
339   //
340   FamilyServices->GetPstateMaxState (FamilyServices, &TempVar_c, &BoostStates, StdHeader);
341   PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue = (UINT8) TempVar_c;
342   PStateBufferPtr->PStateCoreStruct[0].NumberOfBoostedStates = BoostStates;
343
344   for (k = 0; k <= TempVar_c; k++) {
345     // Check if PState is enabled
346     FamilyServices->GetPstateRegisterInfo (        FamilyServices,
347                                                    k,
348                                                    &PStateEnabled,
349                                                    &IddVal,
350                                                    &IddDiv,
351                                                    &SwPstate,
352                                                    StdHeader);
353
354     LibAmdMemFill (&(PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k]), 0, sizeof (S_PSTATE_VALUES), StdHeader);
355
356     if (PStateEnabled) {
357       FamilyServices->GetPstateFrequency (
358         FamilyServices,
359         (UINT8) k,
360         &(PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].CoreFreq),
361         StdHeader);
362
363       FamilyServices->GetPstatePower (
364         FamilyServices,
365         (UINT8) k,
366         &(PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].Power),
367         StdHeader);
368
369       PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].IddValue = IddVal;
370       PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].IddDiv = IddDiv;
371       PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber = SwPstate;
372
373       PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].PStateEnable  = 1;
374       TotalEnabledPStates++;
375     }
376   } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
377
378   // Don't create ACPI Tables if there is one or less than one PState is enabled
379   if (TotalEnabledPStates <= 1) {
380     PStateBufferPtr[0].CreateAcpiTables = 0;
381   }
382
383   //--------------------Check Again--------------------------------
384
385   IdentifyCore (StdHeader, &Socket, &NodeNum, &CoreNum, &IgnoredSts);
386   // Get the PCI address of internal die 0 as it is the only die programmed.
387   GetPciAddress (StdHeader, Socket, 0, &PciAddress, &IgnoredSts);
388   PciAddress.Address.Function = FUNC_3;
389   PciAddress.Address.Register = NORTH_BRIDGE_CAPABILITIES_REG;
390   TempVar_c = 0;
391   LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_c, StdHeader);
392   PStateBufferPtr->PStateCoreStruct[0].HtcCapable =
393     (UINT8) ((TempVar_c & 0x00000400) >> 10);    // Bit  10
394
395   TempVar_c = 0;
396   PciAddress.Address.Register = HARDWARE_THERMAL_CTRL_REG;
397   LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_c, StdHeader);
398   PStateBufferPtr->PStateCoreStruct[0].HtcPstateLimit =
399     (UINT8) ((TempVar_c & 0x70000000) >> 28);   // Bits 30:28
400
401   // Get LocalApicId from CPUID Fn0000_0001_EBX
402   LibAmdCpuidRead (AMD_CPUID_APICID_LPC_BID, &CpuId, StdHeader);
403   PStateBufferPtr->PStateCoreStruct[0].LocalApicId = (UINT8) ((CpuId.EBX_Reg & 0xFF000000) >> 24);
404 }
405
406
407 /*----------------------------------------------------------------------------
408  *                              LOCAL FUNCTIONS
409  *
410  *----------------------------------------------------------------------------
411  */