AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / cpuPostInit.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD CPU POST API, and related functions.
6  *
7  * Contains code that initialized the CPU after memory init.
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  * AMD Generic Encapsulated Software Architecture
18  *
19  * Description: cpuPostInit.c - Cpu POST Initialization Functions.
20  *
21  ******************************************************************************
22  *
23  * Copyright (C) 2012 Advanced Micro Devices, Inc.
24  * All rights reserved.
25  *
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted provided that the following conditions are met:
28  *     * Redistributions of source code must retain the above copyright
29  *       notice, this list of conditions and the following disclaimer.
30  *     * Redistributions in binary form must reproduce the above copyright
31  *       notice, this list of conditions and the following disclaimer in the
32  *       documentation and/or other materials provided with the distribution.
33  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
34  *       its contributors may be used to endorse or promote products derived
35  *       from this software without specific prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
38  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
41  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  *
48  ******************************************************************************
49  */
50
51 /*----------------------------------------------------------------------------------------
52  *                             M O D U L E S    U S E D
53  *----------------------------------------------------------------------------------------
54  */
55
56 #include "AGESA.h"
57 #include "amdlib.h"
58 #include "Ids.h"
59 #include "Options.h"
60 #include "cpuRegisters.h"
61 #include "cpuApicUtilities.h"
62 #include "heapManager.h"
63 #include "cpuServices.h"
64 #include "cpuFeatures.h"
65 #include "GeneralServices.h"
66 #include "cpuPostInit.h"
67 #include "cpuPstateTables.h"
68 #include "cpuFamilyTranslation.h"
69 #include "Filecode.h"
70 CODE_GROUP (G1_PEICC)
71 RDATA_GROUP (G2_PEI)
72 #define FILECODE PROC_CPU_CPUPOSTINIT_FILECODE
73 /*----------------------------------------------------------------------------------------
74  *                   D E F I N I T I O N S    A N D    M A C R O S
75  *----------------------------------------------------------------------------------------
76  */
77
78 /*----------------------------------------------------------------------------------------
79  *                  T Y P E D E F S     A N D     S T R U C T U R E S
80  *----------------------------------------------------------------------------------------
81  */
82
83 /*----------------------------------------------------------------------------------------
84  *           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
85  *----------------------------------------------------------------------------------------
86  */
87 VOID
88 STATIC
89 SyncVariableMTRR (
90   IN       AMD_CONFIG_PARAMS  *StdHeader
91   );
92
93 /*----------------------------------------------------------------------------------------
94  *                          E X P O R T E D    F U N C T I O N S
95  *----------------------------------------------------------------------------------------
96  */
97 extern BUILD_OPT_CFG UserOptions;
98 extern CPU_FAMILY_SUPPORT_TABLE            PstateFamilyServiceTable;
99
100 extern
101 VOID
102 ExecuteWbinvdInstruction (
103   IN OUT   AMD_CONFIG_PARAMS *StdHeader
104   );
105
106 AGESA_STATUS
107 PstateCreateHeapInfo (
108   IN       PLATFORM_CONFIGURATION *PlatformConfig,
109   IN       AMD_CONFIG_PARAMS *StdHeader
110   );
111
112 /*---------------------------------------------------------------------------------------*/
113 /**
114  * Performs CPU related initialization at the POST entry point
115  *
116  * This function performs a large list of initialization items.  These items
117  * include:
118  *
119  *    -1      AP MTRR sync
120  *    -2      feature leveling
121  *    -3      P-state data gather
122  *    -4      P-state leveling
123  *    -5      AP cache breakdown & release
124  *
125  * @param[in]  StdHeader         Config handle for library and services
126  * @param[in]  PlatformConfig    Config handle for platform specific information
127  *
128  * @retval     AGESA_SUCCESS
129  *
130  */
131 AGESA_STATUS
132 AmdCpuPost (
133   IN       AMD_CONFIG_PARAMS *StdHeader,
134   IN       PLATFORM_CONFIGURATION *PlatformConfig
135   )
136 {
137   AGESA_STATUS AgesaStatus;
138   AGESA_STATUS CalledStatus;
139
140   AgesaStatus = AGESA_SUCCESS;
141   //
142   // Sync variable MTRR
143   //
144   AGESA_TESTPOINT (TpProcCpuApMtrrSync, StdHeader);
145   SyncVariableMTRR (StdHeader);
146
147   AGESA_TESTPOINT (TpProcCpuPostFeatureInit, StdHeader);
148   IDS_HDT_CONSOLE (CPU_TRACE, "  Dispatch CPU features after AP MTRR sync\n");
149   CalledStatus = DispatchCpuFeatures (CPU_FEAT_AFTER_POST_MTRR_SYNC, PlatformConfig, StdHeader);
150   if (CalledStatus > AgesaStatus) {
151     AgesaStatus = CalledStatus;
152   }
153   //
154   // Feature Leveling
155   //
156   AGESA_TESTPOINT (TpProcCpuFeatureLeveling, StdHeader);
157   IDS_HDT_CONSOLE (CPU_TRACE, "  Perform feature leveling\n");
158   FeatureLeveling (StdHeader);
159   //
160   // P-state Gathered and set heap info
161   //
162   IDS_HDT_CONSOLE (CPU_TRACE, "  Create P-state info in the heap\n");
163   PstateCreateHeapInfo (PlatformConfig, StdHeader);
164
165   // Set TscFreqSel at the rate specified by the core P0 after core frequency leveling.
166   SetCoresTscFreqSel (StdHeader);
167
168   // Dispatch CPU features before relinquishing control of APs
169   AGESA_TESTPOINT (TpProcCpuBeforeRelinquishAPsFeatureInit, StdHeader);
170   IDS_HDT_CONSOLE (CPU_TRACE, "  Dispatch CPU features before Relinquishing control of APs\n");
171   CalledStatus = DispatchCpuFeatures (CPU_FEAT_BEFORE_RELINQUISH_AP, PlatformConfig, StdHeader);
172   if (CalledStatus > AgesaStatus) {
173     AgesaStatus = CalledStatus;
174   }
175
176   // Relinquish control of all APs to IBV.
177   IDS_HDT_CONSOLE (CPU_TRACE, "  Relinquish control of APs\n");
178   RelinquishControlOfAllAPs (StdHeader);
179
180   return (AgesaStatus);
181 }
182
183 /*---------------------------------------------------------------------------------------
184  *                           L O C A L    F U N C T I O N S
185  *---------------------------------------------------------------------------------------
186  */
187
188 /*---------------------------------------------------------------------------------------*/
189 /**
190  * Determines the address in system DRAM that should be used for p-state data
191  * gather and leveling.
192  *
193  * @param[out] Ptr               Address to utilize
194  * @param[in]  StdHeader         Config handle for library and services
195  *
196  * @retval     AGESA_SUCCESS
197  *
198  */
199 AGESA_STATUS
200 GetPstateGatherDataAddressAtPost (
201      OUT   UINT64            **Ptr,
202   IN       AMD_CONFIG_PARAMS *StdHeader
203   )
204 {
205   UINT64 AddressValue;
206
207   AddressValue = P_STATE_DATA_GATHER_TEMP_ADDR;
208
209   *Ptr = (UINT64 *)(AddressValue);
210
211   return AGESA_SUCCESS;
212 }
213
214
215 /*---------------------------------------------------------------------------------------*/
216 /**
217  * AP task to sync memory subsystem MSRs with the BSC
218  *
219  * This function processes a list of MSRs and the BSC's current values for those
220  * MSRs.  This will allow the APs to see system RAM.
221  *
222  * @param[in]  MtrrTable         Memory related MSR table
223  * @param[in]  StdHeader         Config handle for library and services
224  *
225  */
226 VOID
227 SyncAllApMtrrToBsc (
228   IN       VOID *MtrrTable,
229   IN       AMD_CONFIG_PARAMS *StdHeader
230   )
231 {
232   UINT8   i;
233
234   for (i = 0; ((BSC_AP_MSR_SYNC *) MtrrTable)[i].RegisterAddress != 0; i++) {
235     LibAmdMsrWrite (((BSC_AP_MSR_SYNC *) MtrrTable)[i].RegisterAddress,
236                     &((BSC_AP_MSR_SYNC *) MtrrTable)[i].RegisterValue,
237                     StdHeader);
238   }
239 }
240
241
242 /*---------------------------------------------------------------------------------------*/
243 /**
244  * Creates p-state information on the heap
245  *
246  * This function gathers p-state information from all processors in the system,
247  * determines a level set of p-states, and places that information into the
248  * heap.  This heap data will be used by GenerateSsdt to generate the
249  * final _PSS and XPSS objects.
250  *
251  * @param[in]  PlatformConfig    Pointer to runtime configuration options
252  * @param[in]  StdHeader         Config handle for library and services
253  *
254  * @retval     AGESA_SUCCESS     No error
255  * @retval     AGESA_ERROR       CPU_ERROR_PSTATE_HEAP_NOT_AVAILABLE
256  */
257 AGESA_STATUS
258 PstateCreateHeapInfo (
259   IN       PLATFORM_CONFIGURATION *PlatformConfig,
260   IN       AMD_CONFIG_PARAMS   *StdHeader
261   )
262 {
263   AGESA_STATUS            AgesaStatus;
264   S_CPU_AMD_PSTATE        *PStateBufferPtr;
265   ALLOCATE_HEAP_PARAMS    AllocHeapParams;
266   UINT8                   *PStateBufferPtrInHeap;
267
268   ASSERT (IsBsp (StdHeader, &AgesaStatus));
269
270   //
271   //Get proper address for gather data pool address
272   //Zero P-state gather data pool
273   //
274   GetPstateGatherDataAddressAtPost ((UINT64 **)&PStateBufferPtr, StdHeader);
275   LibAmdMemFill (PStateBufferPtr, 0, sizeof (S_CPU_AMD_PSTATE), StdHeader);
276
277   //
278   //Get all the CPUs P-States and fill the PStateBufferPtr for each core
279   //
280   AgesaStatus = PStateGatherData (PlatformConfig, PStateBufferPtr, StdHeader);
281   if (AgesaStatus != AGESA_SUCCESS) {
282     return AgesaStatus;
283   }
284
285   //
286   //Do Pstate Leveling for each core if needed.
287   //
288   AgesaStatus = PStateLeveling (PStateBufferPtr, StdHeader);
289
290   //
291   //Create Heap and store p-state data for ACPI table in CpuLate
292   //
293   AllocHeapParams.RequestedBufferSize = PStateBufferPtr->SizeOfBytes;
294   AllocHeapParams.BufferHandle = AMD_PSTATE_DATA_BUFFER_HANDLE;
295   AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
296   AgesaStatus = HeapAllocateBuffer (&AllocHeapParams, StdHeader);
297   if (AgesaStatus == AGESA_SUCCESS) {
298     //
299     // Zero Buffer
300     //
301     PStateBufferPtrInHeap = (UINT8 *) AllocHeapParams.BufferPtr;
302     LibAmdMemFill (PStateBufferPtrInHeap, 0, PStateBufferPtr->SizeOfBytes, StdHeader);
303     LibAmdMemCopy  (PStateBufferPtrInHeap, PStateBufferPtr, PStateBufferPtr->SizeOfBytes, StdHeader);
304
305   } else {
306     PutEventLog (AGESA_ERROR,
307                    CPU_ERROR_PSTATE_HEAP_NOT_AVAILABLE,
308                  0, 0, 0, 0, StdHeader);
309   }
310
311   return AgesaStatus;
312 }
313
314 VOID
315 SyncApMsrsToBsc (
316   IN OUT   BSC_AP_MSR_SYNC    *ApMsrSync,
317   IN       AMD_CONFIG_PARAMS  *StdHeader
318   )
319 {
320   AP_TASK                 TaskPtr;
321   UINT16                  i;
322   UINT32                  BscSocket;
323   UINT32                  Ignored;
324   UINT32                  BscCoreNum;
325   UINT32                  Core;
326   UINT32                  Socket;
327   UINT32                  NumberOfSockets;
328   UINT32                  NumberOfCores;
329   AGESA_STATUS            IgnoredSts;
330
331   ASSERT (IsBsp (StdHeader, &IgnoredSts));
332
333   IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
334   NumberOfSockets = GetPlatformNumberOfSockets ();
335
336   //
337   //Sync all MTRR settings with BSP
338   //
339   for (i = 0; ApMsrSync[i].RegisterAddress != 0; i++) {
340     LibAmdMsrRead (ApMsrSync[i].RegisterAddress, &ApMsrSync[i].RegisterValue, StdHeader);
341   }
342
343   TaskPtr.FuncAddress.PfApTaskI = SyncAllApMtrrToBsc;
344   TaskPtr.DataTransfer.DataSizeInDwords = (UINT16) ((((sizeof (BSC_AP_MSR_SYNC)) * i) + 4) >> 2);
345   TaskPtr.ExeFlags = WAIT_FOR_CORE;
346   TaskPtr.DataTransfer.DataPtr = ApMsrSync;
347   TaskPtr.DataTransfer.DataTransferFlags = 0;
348
349   for (Socket = 0; Socket < NumberOfSockets; Socket++) {
350     if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
351       for (Core = 0; Core < NumberOfCores; Core++) {
352         if ((Socket != BscSocket) || (Core != BscCoreNum)) {
353           ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
354         }
355       }
356     }
357   }
358 }
359
360 /*---------------------------------------------------------------------------------------*/
361 /**
362  * SyncVariableMTRR
363  *
364  * Sync variable MTRR
365  *
366  * @param[in]  StdHeader         Config handle for library and services
367  *
368  */
369 VOID
370 STATIC
371 SyncVariableMTRR (
372   IN       AMD_CONFIG_PARAMS  *StdHeader
373   )
374 {
375   BSC_AP_MSR_SYNC ApMsrSync[20];
376
377   ApMsrSync[0].RegisterAddress = SYS_CFG;
378   ApMsrSync[1].RegisterAddress = TOP_MEM;
379   ApMsrSync[2].RegisterAddress = TOP_MEM2;
380   ApMsrSync[3].RegisterAddress = 0x200;
381   ApMsrSync[4].RegisterAddress = 0x201;
382   ApMsrSync[5].RegisterAddress = 0x202;
383   ApMsrSync[6].RegisterAddress = 0x203;
384   ApMsrSync[7].RegisterAddress = 0x204;
385   ApMsrSync[8].RegisterAddress = 0x205;
386   ApMsrSync[9].RegisterAddress = 0x206;
387   ApMsrSync[10].RegisterAddress = 0x207;
388   ApMsrSync[11].RegisterAddress = 0x208;
389   ApMsrSync[12].RegisterAddress = 0x209;
390   ApMsrSync[13].RegisterAddress = 0x20A;
391   ApMsrSync[14].RegisterAddress = 0x20B;
392   ApMsrSync[15].RegisterAddress = 0xC0010016;
393   ApMsrSync[16].RegisterAddress = 0xC0010017;
394   ApMsrSync[17].RegisterAddress = 0xC0010018;
395   ApMsrSync[18].RegisterAddress = 0xC0010019;
396   ApMsrSync[19].RegisterAddress = 0;
397   SyncApMsrsToBsc (ApMsrSync, StdHeader);
398 }
399
400 /*---------------------------------------------------------------------------------------*/
401 /**
402  * The function suppose to do any thing need to be done at the end of AmdInitPost.
403  *
404  * @param[in]  StdHeader         Config handle for library and services
405  *
406  * @retval     AGESA_SUCCESS
407  *
408  */
409 AGESA_STATUS
410 FinalizeAtPost (
411   IN       AMD_CONFIG_PARAMS *StdHeader
412   )
413 {
414   //
415   // Execute wbinvd to ensure heap data in cache write back to memory.
416   //
417   ExecuteWbinvdInstruction (StdHeader);
418
419   return AGESA_SUCCESS;
420 }
421 /*---------------------------------------------------------------------------------------*/
422 /**
423  * Set TSC Frequency Selection.
424  *
425  * This function set TSC Frequency Selection.
426  *
427  * @param[in]  StdHeader         Config handle for library and services
428  *
429  */
430 VOID
431 STATIC
432 SetTscFreqSel (
433   IN       AMD_CONFIG_PARAMS *StdHeader
434   )
435 {
436   PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
437
438   FamilyServices = NULL;
439
440   GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
441   if (FamilyServices != NULL) {
442     FamilyServices->CpuSetTscFreqSel (FamilyServices, StdHeader);
443   }
444
445 }
446
447 /*---------------------------------------------------------------------------------------*/
448 /**
449  * Set TSC Frequency Selection to all cores.
450  *
451  * This function set TscFreqSel to all cores in the system.
452  *
453  * @param[in]  StdHeader         Config handle for library and services
454  *
455  */
456 VOID
457 SetCoresTscFreqSel (
458   IN       AMD_CONFIG_PARAMS   *StdHeader
459   )
460 {
461   AP_TASK                 TaskPtr;
462   UINT32                  BscSocket;
463   UINT32                  Ignored;
464   UINT32                  BscCoreNum;
465   UINT32                  Core;
466   UINT32                  Socket;
467   UINT32                  NumberOfSockets;
468   UINT32                  NumberOfCores;
469   AGESA_STATUS            IgnoredSts;
470
471   ASSERT (IsBsp (StdHeader, &IgnoredSts));
472
473   IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
474   NumberOfSockets = GetPlatformNumberOfSockets ();
475
476   SetTscFreqSel (StdHeader);
477
478   TaskPtr.FuncAddress.PfApTask = SetTscFreqSel;
479   TaskPtr.ExeFlags = WAIT_FOR_CORE;
480   TaskPtr.DataTransfer.DataTransferFlags = 0;
481   TaskPtr.DataTransfer.DataSizeInDwords = 0;
482   TaskPtr.DataTransfer.DataPtr = NULL;
483
484   for (Socket = 0; Socket < NumberOfSockets; Socket++) {
485     if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
486       for (Core = 0; Core < NumberOfCores; Core++) {
487         if ((Socket != BscSocket) || (Core != BscCoreNum)) {
488           ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
489         }
490       }
491     }
492   }
493 }