AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / Family / 0x10 / RevC / F10RevCUtilities.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD Family_10 revision Cx specific utility functions.
6  *
7  * Provides numerous utility functions specific to family 10h rev C.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  CPU/F10
12  * @e \$Revision: 56279 $   @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
13  *
14  */
15 /*
16  ******************************************************************************
17  *
18  * Copyright (C) 2012 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  *                             M O D U L E S    U S E D
48  *----------------------------------------------------------------------------------------
49  */
50 #include "AGESA.h"
51 #include "amdlib.h"
52 #include "Ids.h"
53 #include "cpuRegisters.h"
54 #include "cpuFamilyTranslation.h"
55 #include "cpuF10PowerMgmt.h"
56 #include "GeneralServices.h"
57 #include "cpuEarlyInit.h"
58 #include "cpuPostInit.h"
59 #include "cpuFeatures.h"
60 #include "OptionMultiSocket.h"
61 #include "Filecode.h"
62 CODE_GROUP (G1_PEICC)
63 RDATA_GROUP (G2_PEI)
64 #define FILECODE PROC_CPU_FAMILY_0X10_REVC_F10REVCUTILITIES_FILECODE
65
66 /*----------------------------------------------------------------------------------------
67  *                   D E F I N I T I O N S    A N D    M A C R O S
68  *----------------------------------------------------------------------------------------
69  */
70 extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
71 /*----------------------------------------------------------------------------------------
72  *                  T Y P E D E F S     A N D     S T R U C T U R E S
73  *----------------------------------------------------------------------------------------
74  */
75
76 /*----------------------------------------------------------------------------------------
77  *           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
78  *----------------------------------------------------------------------------------------
79  */
80
81 /*----------------------------------------------------------------------------------------
82  *                          E X P O R T E D    F U N C T I O N S
83  *----------------------------------------------------------------------------------------
84  */
85
86 /*---------------------------------------------------------------------------------------*/
87 /**
88  * Set down core register on a revision C processor.
89  *
90  * This function set F3x190 Downcore Control Register[5:0]
91  *
92  * @param[in]   FamilySpecificServices   The current Family Specific Services.
93  * @param[in]   Socket                   Socket ID.
94  * @param[in]   Module                   Module ID in socket.
95  * @param[in]   LeveledCores             Number of core.
96  * @param[in]   CoreLevelMode            Core level mode.
97  * @param[in]   StdHeader                Header for library and services.
98  *
99  * @retval      TRUE                     Down Core register is updated.
100  * @retval      FALSE                    Down Core register is not updated.
101  */
102 BOOLEAN
103 F10CommonRevCSetDownCoreRegister (
104   IN       CPU_CORE_LEVELING_FAMILY_SERVICES *FamilySpecificServices,
105   IN       UINT32 *Socket,
106   IN       UINT32 *Module,
107   IN       UINT32 *LeveledCores,
108   IN       CORE_LEVELING_TYPE CoreLevelMode,
109   IN       AMD_CONFIG_PARAMS *StdHeader
110   )
111 {
112   UINT32    TempVar32_a;
113   UINT32    CoreDisableBits;
114   PCI_ADDR  PciAddress;
115   BOOLEAN   IsUpdated;
116   AGESA_STATUS AgesaStatus;
117
118   IsUpdated = FALSE;
119
120   switch (*LeveledCores) {
121   case 1:
122     CoreDisableBits = DOWNCORE_MASK_SINGLE;
123     break;
124   case 2:
125     CoreDisableBits = DOWNCORE_MASK_DUAL;
126     break;
127   case 3:
128     CoreDisableBits = DOWNCORE_MASK_TRI;
129     break;
130   default:
131     CoreDisableBits = 0;
132     break;
133   }
134
135   if (CoreDisableBits != 0) {
136     if (GetPciAddress (StdHeader, (UINT8) *Socket, (UINT8) *Module, &PciAddress, &AgesaStatus)) {
137       PciAddress.Address.Function = FUNC_3;
138       PciAddress.Address.Register = NORTH_BRIDGE_CAPABILITIES_REG;
139
140       LibAmdPciRead (AccessWidth32, PciAddress, &TempVar32_a, StdHeader);
141       TempVar32_a = (TempVar32_a >> 12) & 0x3;
142       if (TempVar32_a == 0) {
143         CoreDisableBits &= 0x1;
144       } else if (TempVar32_a == 1) {
145         CoreDisableBits &= 0x3;
146       } else if (TempVar32_a == 2) {
147         CoreDisableBits &= 0x7;
148       } else if (TempVar32_a == 3) {
149         CoreDisableBits &= 0x0F;
150       }
151       PciAddress.Address.Register = DOWNCORE_CTRL;
152       LibAmdPciRead (AccessWidth32, PciAddress, &TempVar32_a, StdHeader);
153       if ((TempVar32_a | CoreDisableBits) != TempVar32_a) {
154         TempVar32_a |= CoreDisableBits;
155         LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar32_a, StdHeader);
156         IsUpdated = TRUE;
157       }
158     }
159   }
160
161   return IsUpdated;
162 }
163
164
165 CONST CPU_CORE_LEVELING_FAMILY_SERVICES ROMDATA F10RevCCoreLeveling =
166 {
167   0,
168   F10CommonRevCSetDownCoreRegister
169 };
170
171
172 /*---------------------------------------------------------------------------------------*/
173 /**
174  *  Get CPU pstate current on a revision C processor.
175  *
176  *  @CpuServiceMethod{::F_CPU_GET_IDD_MAX}.
177  *
178  *    This function returns the ProcIddMax.
179  *
180  *  @param[in]     FamilySpecificServices    The current Family Specific Services.
181  *  @param[in]     Pstate                    The P-state to check.
182  *  @param[out]    ProcIddMax                P-state current in mA.
183  *  @param[in]     StdHeader                 Handle of Header for calling lib functions and services.
184  *
185  *  @retval        TRUE                      P-state is enabled
186  *  @retval        FALSE                     P-state is disabled
187  */
188 BOOLEAN
189 F10CommonRevCGetProcIddMax (
190   IN       CPU_SPECIFIC_SERVICES  *FamilySpecificServices,
191   IN       UINT8                  Pstate,
192      OUT   UINT32                 *ProcIddMax,
193   IN       AMD_CONFIG_PARAMS      *StdHeader
194   )
195 {
196   UINT32       IddDiv;
197   UINT32       CmpCap;
198   UINT32       LocalPciRegister;
199   UINT32       MsrAddress;
200   UINT32       SinglePlaneNbIdd;
201   UINT64       PstateMsr;
202   BOOLEAN      IsPstateEnabled;
203   PCI_ADDR     PciAddress;
204
205   IsPstateEnabled = FALSE;
206
207   MsrAddress = (UINT32) (Pstate + PS_REG_BASE);
208
209   ASSERT (MsrAddress <= PS_MAX_REG);
210
211   LibAmdMsrRead (MsrAddress, &PstateMsr, StdHeader);
212   if (((PSTATE_MSR *) &PstateMsr)->PsEnable == 1) {
213     OptionMultiSocketConfiguration.GetCurrPciAddr (&PciAddress, StdHeader);
214
215     PciAddress.Address.Function = FUNC_3;
216     PciAddress.Address.Register = NB_CAPS_REG;
217     LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F3xE8
218     CmpCap = (UINT32) (((NB_CAPS_REGISTER *) &LocalPciRegister)->CmpCapLo);
219     CmpCap++;
220
221     switch (((PSTATE_MSR *) &PstateMsr)->IddDiv) {
222     case 0:
223       IddDiv = 1000;
224       break;
225     case 1:
226       IddDiv = 100;
227       break;
228     case 2:
229       IddDiv = 10;
230       break;
231     default:  // IddDiv = 3 is reserved. Use 10
232       ASSERT (FALSE);
233       IddDiv = 10;
234       break;
235     }
236
237     PciAddress.Address.Register = PW_CTL_MISC_REG;
238     LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F3xE8
239     if (((POWER_CTRL_MISC_REGISTER *) &LocalPciRegister)->PviMode == 1) {
240       *ProcIddMax = (UINT32) ((PSTATE_MSR *) &PstateMsr)->IddValue * IddDiv * CmpCap;
241     } else {
242       PciAddress.Address.Register = PRCT_INFO_REG;
243       LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F3xE8
244       SinglePlaneNbIdd = ((PRODUCT_INFO_REGISTER *) &LocalPciRegister)->SinglePlaneNbIdd;
245       SinglePlaneNbIdd <<= 1;
246       *ProcIddMax = ((UINT32) ((PSTATE_MSR *) &PstateMsr)->IddValue * IddDiv * CmpCap) - SinglePlaneNbIdd;
247     }
248     IsPstateEnabled = TRUE;
249   }
250   return IsPstateEnabled;
251 }
252
253 /*---------------------------------------------------------------------------------------*/
254 /**
255  *  Returns whether or not BIOS is responsible for configuring the NB COFVID.
256  *
257  *  @CpuServiceMethod{::F_CPU_IS_NBCOF_INIT_NEEDED}.
258  *
259  *  @param[in]   FamilySpecificServices   The current Family Specific Services.
260  *  @param[in]   PciAddress               The northbridge to query by pci base address.
261  *  @param[out]  NbVidUpdateAll           Do all NbVids need to be updated
262  *  @param[in]   StdHeader                Header for library and services
263  *
264  *  @retval      TRUE                    Perform northbridge frequency and voltage config.
265  *  @retval      FALSE                   Do not configure them.
266  */
267 BOOLEAN
268 F10CommonRevCGetNbCofVidUpdate (
269   IN       CPU_SPECIFIC_SERVICES *FamilySpecificServices,
270   IN       PCI_ADDR *PciAddress,
271      OUT   BOOLEAN *NbVidUpdateAll,
272   IN       AMD_CONFIG_PARAMS *StdHeader
273   )
274 {
275   UINT32 ProductInfoRegister;
276
277   PciAddress->Address.Register = PRCT_INFO_REG;
278   PciAddress->Address.Function = FUNC_3;
279   LibAmdPciRead (AccessWidth32, *PciAddress, &ProductInfoRegister, StdHeader);
280   *NbVidUpdateAll = (BOOLEAN) (((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->NbVidUpdateAll == 1);
281   return (BOOLEAN) (((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->NbCofVidUpdate == 1);
282 }
283
284 /*---------------------------------------------------------------------------------------*/
285 /**
286  *  Determines the NB clock on the desired node.
287  *
288  *  @CpuServiceMethod{::F_CPU_GET_NB_PSTATE_INFO}.
289  *
290  *  @param[in]     FamilySpecificServices  The current Family Specific Services.
291  *  @param[in]     PlatformConfig          Platform profile/build option config structure.
292  *  @param[in]     PciAddress              The segment, bus, and device numbers of the CPU in question.
293  *  @param[in]     NbPstate                The NB P-state number to check.
294  *  @param[out]    FreqNumeratorInMHz      The desired node's frequency numerator in megahertz.
295  *  @param[out]    FreqDivisor             The desired node's frequency divisor.
296  *  @param[out]    VoltageInuV             The desired node's voltage in microvolts.
297  *  @param[in]     StdHeader               Handle of Header for calling lib functions and services.
298  *
299  *  @retval        TRUE                    NbPstate is valid
300  *  @retval        FALSE                   NbPstate is disabled or invalid
301  */
302 BOOLEAN
303 F10CommonRevCGetNbPstateInfo (
304   IN       CPU_SPECIFIC_SERVICES  *FamilySpecificServices,
305   IN       PLATFORM_CONFIGURATION *PlatformConfig,
306   IN       PCI_ADDR               *PciAddress,
307   IN       UINT32                 NbPstate,
308      OUT   UINT32                 *FreqNumeratorInMHz,
309      OUT   UINT32                 *FreqDivisor,
310      OUT   UINT32                 *VoltageInuV,
311   IN       AMD_CONFIG_PARAMS      *StdHeader
312   )
313 {
314   UINT32   NbFid;
315   UINT32   NbVid;
316   UINT32   LocalPciRegister;
317   UINT32   ProductInfoRegister;
318   UINT64   LocalMsrRegister;
319   BOOLEAN  PstateIsValid;
320
321   PstateIsValid = TRUE;
322   if (NbPstate == 0) {
323     *FreqDivisor = 1;
324   } else if ((NbPstate == 1) && FamilySpecificServices->IsNbPstateEnabled (FamilySpecificServices, PlatformConfig, StdHeader)) {
325     *FreqDivisor = 2;
326   } else {
327     PstateIsValid = FALSE;
328   }
329   if (PstateIsValid) {
330     PciAddress->Address.Function = FUNC_3;
331     PciAddress->Address.Register = PRCT_INFO_REG;
332     LibAmdPciRead (AccessWidth32, *PciAddress, &ProductInfoRegister, StdHeader);
333     if ((((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->NbCofVidUpdate) == 0) {
334       PciAddress->Address.Register = CPTC0_REG;
335       LibAmdPciRead (AccessWidth32, *PciAddress, &LocalPciRegister, StdHeader);
336       NbFid = ((CLK_PWR_TIMING_CTRL_REGISTER *) &LocalPciRegister)->NbFid;
337       LibAmdMsrRead (MSR_COFVID_STS, &LocalMsrRegister, StdHeader);
338       NbVid = (UINT32) ((COFVID_STS_MSR *) &LocalMsrRegister)->CurNbVid;
339     } else {
340       NbFid = ((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->SinglePlaneNbFid;
341       NbVid = ((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->SinglePlaneNbVid;
342       PciAddress->Address.Register = PW_CTL_MISC_REG;
343       LibAmdPciRead (AccessWidth32, *PciAddress, &LocalPciRegister, StdHeader);
344       if (((POWER_CTRL_MISC_REGISTER *) &LocalPciRegister)->PviMode == 0) {
345         NbFid += ((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->DualPlaneNbFidOff;
346         NbVid -= ((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->DualPlaneNbVidOff;
347       }
348     }
349     *FreqNumeratorInMHz = ((NbFid + 4) * 200);
350     *VoltageInuV = (1550000 - (12500 * NbVid));
351   }
352   return PstateIsValid;
353 }
354
355 /*---------------------------------------------------------------------------------------*/
356 /**
357  *  Returns the node's minimum and maximum northbridge frequency.
358  *
359  *  @CpuServiceMethod{::F_CPU_GET_MIN_MAX_NB_FREQ}.
360  *
361  *  @param[in]     FamilySpecificServices  The current Family Specific Services.
362  *  @param[in]     PlatformConfig          Platform profile/build option config structure.
363  *  @param[in]     PciAddress              The segment, bus, and device numbers of the CPU in question.
364  *  @param[out]    MinFreqInMHz            The node's miminum northbridge frequency.
365  *  @param[out]    MaxFreqInMHz            The node's maximum northbridge frequency.
366  *  @param[in]     StdHeader               Handle of Header for calling lib functions and services.
367  *
368  *  @retval        AGESA_STATUS            Northbridge frequency is valid
369  */
370 AGESA_STATUS
371 F10RevCGetMinMaxNbFrequency (
372   IN       CPU_SPECIFIC_SERVICES  *FamilySpecificServices,
373   IN       PLATFORM_CONFIGURATION *PlatformConfig,
374   IN       PCI_ADDR               *PciAddress,
375      OUT   UINT32                 *MinFreqInMHz,
376      OUT   UINT32                 *MaxFreqInMHz,
377   IN       AMD_CONFIG_PARAMS      *StdHeader
378   )
379 {
380   UINT32         NbPstateEn;
381   UINT32         NbFid;
382   UINT32         FreqDivisor;
383   UINT32         FreqNumerator;
384   UINT32         LocalPciRegister;
385   UINT32         ProductInfoRegister;
386   CPU_LOGICAL_ID LogicalId;
387
388   GetLogicalIdOfCurrentCore (&LogicalId, StdHeader);
389
390   FreqDivisor = 1;
391
392   // If NB P-state is supported, return the frequency of NB P-state 1
393   if ((PlatformConfig->PlatformProfile.PlatformPowerPolicy != Performance) &&
394      ((LogicalId.Revision & AMD_F10_C3) != 0)) {
395     PciAddress->Address.Function = FUNC_3;
396     PciAddress->Address.Register = 0x1F0;
397     LibAmdPciReadBits (*PciAddress, 18, 16, &NbPstateEn, StdHeader);
398
399     if (NbPstateEn != 0) {
400       FreqDivisor = 2;
401     }
402   }
403
404   PciAddress->Address.Function = FUNC_3;
405   PciAddress->Address.Register = PRCT_INFO_REG;
406   LibAmdPciRead (AccessWidth32, *PciAddress, &ProductInfoRegister, StdHeader);
407
408   if ((((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->NbCofVidUpdate) == 0) {
409     PciAddress->Address.Register = CPTC0_REG;
410     LibAmdPciRead (AccessWidth32, *PciAddress, &LocalPciRegister, StdHeader);
411     NbFid = ((CLK_PWR_TIMING_CTRL_REGISTER *) &LocalPciRegister)->NbFid;
412   } else {
413     NbFid = ((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->SinglePlaneNbFid;
414     PciAddress->Address.Register = PW_CTL_MISC_REG;
415     LibAmdPciRead (AccessWidth32, *PciAddress, &LocalPciRegister, StdHeader);
416     if (((POWER_CTRL_MISC_REGISTER *) &LocalPciRegister)->PviMode == 0) {
417       NbFid += ((PRODUCT_INFO_REGISTER *) &ProductInfoRegister)->DualPlaneNbFidOff;
418     }
419   }
420
421   FreqNumerator = ((NbFid + 4) * 200);
422   *MaxFreqInMHz = FreqNumerator;
423   *MinFreqInMHz = (FreqNumerator / FreqDivisor);
424
425   return AGESA_SUCCESS;
426
427 }
428
429 /*---------------------------------------------------------------------------------------*/
430 /**
431  * Is the Northbridge PState feature enabled?
432  *
433  * @CpuServiceMethod{::F_IS_NB_PSTATE_ENABLED}.
434  *
435  * @param[in]      FamilySpecificServices         The current Family Specific Services.
436  * @param[in]      PlatformConfig                 Platform profile/build option config structure.
437  * @param[in]      StdHeader                      Handle of Header for calling lib functions and services.
438  *
439  * @retval         TRUE                           The NB PState feature is enabled.
440  * @retval         FALSE                          The NB PState feature is not enabled.
441  */
442 BOOLEAN
443 F10CommonRevCIsNbPstateEnabled (
444   IN       CPU_SPECIFIC_SERVICES  *FamilySpecificServices,
445   IN       PLATFORM_CONFIGURATION *PlatformConfig,
446   IN       AMD_CONFIG_PARAMS      *StdHeader
447   )
448 {
449   UINT32         NbPstate;
450   PCI_ADDR       PciAddress;
451   CPU_LOGICAL_ID LogicalId;
452   BOOLEAN        Result;
453
454   Result = FALSE;
455
456   GetLogicalIdOfCurrentCore (&LogicalId, StdHeader);
457   if (((LogicalId.Revision & AMD_F10_C3) != 0) && (!IsNonCoherentHt1 (StdHeader))) {
458     OptionMultiSocketConfiguration.GetCurrPciAddr (&PciAddress, StdHeader);
459     PciAddress.Address.Function = FUNC_3;
460     PciAddress.Address.Register = 0x1F0;
461     LibAmdPciReadBits (PciAddress, 18, 16, &NbPstate, StdHeader);
462     if (NbPstate != 0) {
463       Result = TRUE;
464     }
465   }
466   return Result;
467 }
468
469 /*---------------------------------------------------------------------------------------*/
470 /**
471  * Get the number of physical cores of current processor.
472  *
473  * @CpuServiceMethod{::F_CPU_NUMBER_OF_PHYSICAL_CORES}.
474  *
475  * @param[in]      FamilySpecificServices         The current Family Specific Services.
476  * @param[in]      StdHeader                      Handle of Header for calling lib functions and services.
477  *
478  * @return         The number of physical cores.
479  */
480 UINT8
481 F10CommonRevCGetNumberOfPhysicalCores (
482   IN       CPU_SPECIFIC_SERVICES  *FamilySpecificServices,
483   IN       AMD_CONFIG_PARAMS      *StdHeader
484   )
485 {
486   UINT32       LocalPciRegister;
487   PCI_ADDR     PciAddress;
488
489   OptionMultiSocketConfiguration.GetCurrPciAddr (&PciAddress, StdHeader);
490   PciAddress.Address.Function = FUNC_3;
491   PciAddress.Address.Register = NB_CAPS_REG;
492   LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
493   return (UINT8) (((NB_CAPS_REGISTER *) &LocalPciRegister)->CmpCapLo + 1);
494 }
495