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