Add constants for fast path resume copying
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / Family / 0x10 / cpuF10Pstate.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD Family_10 Pstate feature support functions.
6  *
7  * Provides the functions necessary to initialize the Pstate feature.
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 "GeneralServices.h"
53 #include "cpuPstateTables.h"
54 #include "Table.h"
55 #include "cpuFamilyTranslation.h"
56 #include "cpuFamRegisters.h"
57 #include "cpuF10Utilities.h"
58 #include "cpuF10PowerMgmt.h"
59 #include "CommonReturns.h"
60 #include "OptionMultiSocket.h"
61 #include "Filecode.h"
62 CODE_GROUP (G1_PEICC)
63 RDATA_GROUP (G2_PEI)
64
65 #define FILECODE PROC_CPU_FAMILY_0X10_CPUF10PSTATE_FILECODE
66
67 /*----------------------------------------------------------------------------------------
68  *                   D E F I N I T I O N S    A N D    M A C R O S
69  *----------------------------------------------------------------------------------------
70  */
71
72 /*----------------------------------------------------------------------------------------
73  *                  T Y P E D E F S     A N D     S T R U C T U R E S
74  *----------------------------------------------------------------------------------------
75  */
76
77 /*----------------------------------------------------------------------------------------
78  *           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
79  *----------------------------------------------------------------------------------------
80  */
81
82 AGESA_STATUS
83 F10GetPstateTransLatency (
84   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
85   IN       PSTATE_LEVELING        *PStateLevelingBufferStructPtr,
86   IN       PCI_ADDR               *PciAddress,
87      OUT   UINT32                 *TransitionLatency,
88   IN       AMD_CONFIG_PARAMS      *StdHeader
89   );
90
91 AGESA_STATUS
92 F10GetPstateFrequency (
93   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
94   IN       UINT8 StateNumber,
95      OUT   UINT32 *FrequencyInMHz,
96   IN       AMD_CONFIG_PARAMS *StdHeader
97   );
98
99 AGESA_STATUS
100 F10PstateLevelingCoreMsrModify (
101   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
102   IN       S_CPU_AMD_PSTATE   *CpuAmdPState,
103   IN       AMD_CONFIG_PARAMS  *StdHeader
104   );
105
106 AGESA_STATUS
107 F10GetPstatePower (
108   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
109   IN       UINT8 StateNumber,
110      OUT   UINT32 *PowerInMw,
111   IN       AMD_CONFIG_PARAMS *StdHeader
112   );
113
114 AGESA_STATUS
115 F10GetPstateMaxState (
116   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
117      OUT   UINT32              *MaxPStateNumber,
118      OUT   UINT8               *NumberOfBoostStates,
119   IN       AMD_CONFIG_PARAMS   *StdHeader
120   );
121
122 AGESA_STATUS
123 F10GetPstateRegisterInfo (
124   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
125   IN       UINT32              PState,
126      OUT   BOOLEAN             *PStateEnabled,
127   IN OUT   UINT32              *IddVal,
128   IN OUT   UINT32              *IddDiv,
129      OUT   UINT32              *SwPstateNumber,
130   IN       AMD_CONFIG_PARAMS   *StdHeader
131   );
132
133 VOID
134 STATIC
135 F10GetPowerStepValueInTime (
136   IN OUT   UINT32  *PowerStepPtr
137   );
138
139 VOID
140 STATIC
141 F10GetPllValueInTime (
142   IN OUT   UINT32  *PllLockTimePtr
143   );
144
145 AGESA_STATUS
146 STATIC
147 F10GetFrequencyXlatRegInfo (
148   IN       PSTATE_CPU_FAMILY_SERVICES  *PstateCpuServices,
149   IN       UINT8                  PStateNumber,
150   IN       UINT32                 Frequency,
151      OUT   UINT32                 *CpuFidPtr,
152      OUT   UINT32                 *CpuDidPtr1,
153      OUT   UINT32                 *CpuDidPtr2,
154   IN       AMD_CONFIG_PARAMS      *StdHeader
155   );
156
157 /*----------------------------------------------------------------------------------------
158  *                          E X P O R T E D    F U N C T I O N S
159  *----------------------------------------------------------------------------------------
160  */
161 extern BUILD_OPT_CFG UserOptions;
162 extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
163 /*---------------------------------------------------------------------------------------*/
164 /**
165  *  Family specific call to check if Pstate PSD is dependent.
166  *
167  * @param[in]     PstateCpuServices  Pstate CPU services.
168  * @param[in,out] PlatformConfig     Contains the runtime modifiable feature input data.
169  * @param[in]     StdHeader          Config Handle for library, services.
170  *
171  * @retval       TRUE               PSD is dependent.
172  * @retval       FALSE              PSD is independent.
173  *
174  */
175 BOOLEAN
176 STATIC
177 F10IsPstatePsdDependent (
178   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
179   IN OUT   PLATFORM_CONFIGURATION *PlatformConfig,
180   IN       AMD_CONFIG_PARAMS *StdHeader
181   )
182 {
183   CPU_LOGICAL_ID         CpuLogicalId;
184   PLATFORM_FEATS         Features;
185
186   // Initialize the union
187   Features.PlatformValue = 0;
188   GetLogicalIdOfCurrentCore (&CpuLogicalId, StdHeader);
189   GetPlatformFeatures (&Features, PlatformConfig, StdHeader);
190
191   //
192   // RevC and later Single link has PSD option, default is dependent.
193   // If multi-link, always return independent.
194   //
195   if ((Features.PlatformFeatures.PlatformSingleLink) && ((CpuLogicalId.Revision & AMD_F10_GT_Bx) != 0)) {
196     if (PlatformConfig->ForcePstateIndependent) {
197       return FALSE;
198     }
199     return TRUE;
200   }
201   return FALSE;
202 }
203
204 /**
205  *  Family specific call to set core TscFreqSel.
206  *
207  * @param[in]     PstateCpuServices  Pstate CPU services.
208  * @param[in]     StdHeader          Config Handle for library, services.
209  *
210  */
211 VOID
212 STATIC
213 F10SetTscFreqSel (
214   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
215   IN       AMD_CONFIG_PARAMS *StdHeader
216   )
217 {
218   UINT64             MsrValue;
219
220   LibAmdMsrRead (MSR_HWCR, &MsrValue, StdHeader);
221   if (UserOptions.OptionMultisocket) {
222     //
223     // If Agesa need to do p-state leveling on multi-socket, changing the P0
224     // frequency after setting this bit has no effect on the TSC rate.
225     //
226     ASSERT ((MsrValue & BIT24) == 0);
227   }
228   MsrValue = MsrValue | BIT24;
229   LibAmdMsrWrite (MSR_HWCR, &MsrValue, StdHeader);
230 }
231
232 /*---------------------------------------------------------------------------------------*/
233 /**
234  *  Family specific call to get Pstate Transition Latency.
235  *
236  *  Calculate TransitionLatency by power step value and pll value.
237  *
238  *  @param[in]     PstateCpuServices                 Pstate CPU services.
239  *  @param[in]     PStateLevelingBufferStructPtr     Pstate row data buffer pointer
240  *  @param[in]     PciAddress                        Pci address
241  *  @param[out]    TransitionLatency                 The transition latency.
242  *  @param[in]     StdHeader                         Header for library and services
243  *
244  *  @retval      AGESA_SUCCESS Always succeeds.
245  */
246 AGESA_STATUS
247 F10GetPstateTransLatency (
248   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
249   IN       PSTATE_LEVELING        *PStateLevelingBufferStructPtr,
250   IN       PCI_ADDR               *PciAddress,
251      OUT   UINT32                 *TransitionLatency,
252   IN       AMD_CONFIG_PARAMS      *StdHeader
253   )
254 {
255   UINT32               TempVar_b;
256   UINT32               TempVar_c;
257   UINT32               TempVar_d;
258   UINT32               TempVar8_a;
259   UINT32               TempVar8_b;
260   UINT32               Ignored;
261   UINT32               k;
262   UINT32               CpuFidSameFlag;
263   UINT8                PStateMaxValueOnCurrentCore;
264   UINT32               TransAndBusMastLatency;
265
266   CpuFidSameFlag = 1;
267
268   F10GetFrequencyXlatRegInfo (
269     PstateCpuServices,
270     0,
271     PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateStruct[0].CoreFreq,
272     &TempVar_b,
273     &TempVar_c,
274     &Ignored,
275     StdHeader
276     );
277
278   TempVar_d = TempVar_b;
279   PStateMaxValueOnCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue;
280
281   //
282   //Check if MSRC001_00[68:64][CpuFid] is the same value for all P-states where
283   //MSRC001_00[68:64][PstateEn]=1
284   //
285   for (k = 1; k <= PStateMaxValueOnCurrentCore; k++) {
286     if (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
287       F10GetFrequencyXlatRegInfo (
288         PstateCpuServices,
289         (UINT8) k,
290         PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateStruct[k].CoreFreq,
291         &TempVar_b,
292         &TempVar_c,
293         &Ignored,
294         StdHeader
295         );
296     }
297
298     if (TempVar_d != TempVar_b) {
299       CpuFidSameFlag = 0;
300       break;
301     }
302   }
303
304   PciAddress->Address.Register = 0xD4;
305   PciAddress->Address.Function = FUNC_3;
306   LibAmdPciRead (AccessWidth32, *PciAddress, &TempVar_d, StdHeader);
307
308   // PowerStepDown - Bits 20:23
309   TempVar8_a = (TempVar_d & 0x00F00000) >> 20;
310
311   // PowerStepUp   - Bits 24:27
312   TempVar8_b = (TempVar_d & 0x0F000000) >> 24;
313
314   // Convert the raw numbers in TempVar8_a and TempVar8_b into time
315   F10GetPowerStepValueInTime (&TempVar8_a);
316   F10GetPowerStepValueInTime (&TempVar8_b);
317
318   //
319   //(12 * (F3xD4[PowerStepDown] + F3xD4[PowerStepUp]) /1000) us
320   //
321   TransAndBusMastLatency =
322   (12 * (TempVar8_a + TempVar8_b) + 999) / 1000;
323
324   if (CpuFidSameFlag == 0) {
325     //
326     //+ F3xA0[PllLockTime]
327     //
328     PciAddress->Address.Register = 0xA0;
329     LibAmdPciRead (AccessWidth32, *PciAddress, &TempVar_d, StdHeader);
330
331     TempVar8_a = (0x00003800 & TempVar_d) >> 11;
332     F10GetPllValueInTime (&TempVar8_a);
333     TransAndBusMastLatency += TempVar8_a;
334   }
335
336   *TransitionLatency = TransAndBusMastLatency;
337
338   return (AGESA_SUCCESS);
339 }
340
341 /*---------------------------------------------------------------------------------------*/
342 /**
343  *  Family specific call to calculates the frequency in megahertz of the desired P-state.
344  *
345  *  @param[in]   PstateCpuServices        Pstate CPU services.
346  *  @param[in]   StateNumber              The P-State to analyze.
347  *  @param[out]  FrequencyInMHz           The P-State's frequency in MegaHertz
348  *  @param[in]   StdHeader                Header for library and services
349  *
350  *  @retval      AGESA_SUCCESS   Always Succeeds.
351  */
352 AGESA_STATUS
353 F10GetPstateFrequency (
354   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
355   IN       UINT8 StateNumber,
356      OUT   UINT32 *FrequencyInMHz,
357   IN       AMD_CONFIG_PARAMS *StdHeader
358   )
359 {
360   UINT8 TempValue;
361   UINT32 CpuDid;
362   UINT32 CpuFid;
363   UINT64 LocalMsrRegister;
364
365   ASSERT (StateNumber < NM_PS_REG);
366   LibAmdMsrRead (PS_REG_BASE + (UINT32) StateNumber, &LocalMsrRegister, StdHeader);
367   ASSERT (((PSTATE_MSR *) &LocalMsrRegister)->PsEnable == 1);
368   CpuDid = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->CpuDid);
369   CpuFid = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->CpuFid);
370
371   switch (CpuDid) {
372   case 0:
373     TempValue = 1;
374     break;
375   case 1:
376     TempValue = 2;
377     break;
378   case 2:
379     TempValue = 4;
380     break;
381   case 3:
382     TempValue = 8;
383     break;
384   case 4:
385     TempValue  =  16;
386     break;
387   default:
388     // CpuDid is set to an undefined value.  This is due to either a misfused CPU, or
389     // an invalid P-state MSR write.
390     ASSERT (FALSE);
391     TempValue = 1;
392     break;
393   }
394   *FrequencyInMHz = (100 * (CpuFid + 0x10) / TempValue);
395   return (AGESA_SUCCESS);
396 }
397
398 /*---------------------------------------------------------------------------------------*/
399 /**
400  * Family specific call to sets the Pstate MSR to each APs base on Pstate Buffer.
401  *
402  * @param[in]       PstateCpuServices        Pstate CPU services.
403  * @param[in]       CpuAmdPState             Gathered P-state data structure for whole system.
404  * @param[in]       StdHeader                Config for library and services.
405  *
406  * @retval          AGESA_SUCCESS            Always succeeds.
407  *
408  */
409 AGESA_STATUS
410 F10PstateLevelingCoreMsrModify (
411   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
412   IN       S_CPU_AMD_PSTATE   *CpuAmdPState,
413   IN       AMD_CONFIG_PARAMS  *StdHeader
414   )
415 {
416   UINT32             i;
417   UINT32             Ignored;
418   UINT32             k;
419   UINT32             TempVar_d;
420   UINT32             TempVar_e;
421   UINT32             TempVar_f;
422   UINT32             LogicalSocketCount;
423   UINT32             LocalPciRegister;
424   UINT32             Socket;
425   UINT32             Module;
426   UINT32             Core;
427   UINT64             MsrValue;
428   AGESA_STATUS       Status;
429   PSTATE_LEVELING    *PStateBufferPtr;
430   PSTATE_LEVELING    *PStateBufferPtrTmp;
431   S_CPU_AMD_PSTATE   *CpuAmdPstatePtr;
432   PCI_ADDR           PciAddress;
433   CPU_SPECIFIC_SERVICES   *FamilySpecificServices;
434
435   GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
436   ASSERT (FamilySpecificServices != NULL);
437
438   Ignored = 0;
439   CpuAmdPstatePtr = (S_CPU_AMD_PSTATE *) CpuAmdPState;
440   PStateBufferPtrTmp = CpuAmdPstatePtr->PStateLevelingStruc;
441   PStateBufferPtr = CpuAmdPstatePtr->PStateLevelingStruc;
442   LogicalSocketCount = CpuAmdPstatePtr->TotalSocketInSystem;
443   PciAddress.AddressValue = 0;
444
445   //
446   //Try to find the Pstate buffer specific to this core(socket).
447   //
448   IdentifyCore (StdHeader, &Socket, &Module, &Core, &Status);
449   for (i = 0; i < LogicalSocketCount; i++) {
450     CpuGetPStateLevelStructure (&PStateBufferPtrTmp, CpuAmdPstatePtr, i, StdHeader);
451     if (PStateBufferPtrTmp->SocketNumber == Socket) {
452       break;
453     }
454   }
455
456   if (PStateBufferPtr[0].OnlyOneEnabledPState) {
457     //
458     //If all processors have only 1 enabled P-state, the following sequence should be performed on all cores:
459     //
460
461     //1. Write the appropriate CpuFid value resulting from the matched CPU COF to MSRC001_0064[CpuFid].
462     LibAmdMsrRead (MSR_PSTATE_0, &MsrValue, StdHeader);
463     Status = F10GetFrequencyXlatRegInfo (PstateCpuServices, 0, PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].CoreFreq, &TempVar_d, &TempVar_e, &Ignored, StdHeader);
464     // Bits 5:0
465     ((PSTATE_MSR *) &MsrValue)->CpuFid = TempVar_d;
466     // Bits 8:6
467     ((PSTATE_MSR *) &MsrValue)->CpuDid = TempVar_e;
468     // Bits 39:32
469     ((PSTATE_MSR *) &MsrValue)->IddValue = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].IddValue;
470     // Bits 41:40
471     ((PSTATE_MSR *) &MsrValue)->IddDiv = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].IddDiv;
472     // Enable the P-State
473     ((PSTATE_MSR *) &MsrValue)->PsEnable = 1;
474     LibAmdMsrWrite (MSR_PSTATE_0, &MsrValue, StdHeader);
475
476     //2. Copy MSRC001_0064 to MSRC001_0065.
477     LibAmdMsrWrite (MSR_PSTATE_1, &MsrValue, StdHeader);
478
479     //3. Write 001b to F3xDC[PstatemaxVal].
480     GetPciAddress (StdHeader, Socket, Module, &PciAddress, &Status);
481     PciAddress.Address.Register = CPTC2_REG;
482     PciAddress.Address.Function = FUNC_3;
483     LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
484     ((CLK_PWR_TIMING_CTRL2_REGISTER *) &LocalPciRegister)->PstateMaxVal = 1;
485     LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
486
487     //4. Write 001b to MSRC001_0062[PstateCmd].
488     FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 1, (BOOLEAN) FALSE, StdHeader);
489
490     //5. Wait for MSRC001_0071[CurCpuFid] = MSRC001_0065[CpuFid].
491     do {
492       LibAmdMsrRead (MSR_COFVID_STS, &MsrValue, StdHeader);
493     } while (((COFVID_STS_MSR *) &MsrValue)->CurCpuFid != TempVar_d);
494
495     //6. Write 000b to MSRC001_0062[PstateCmd].
496     FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 0, (BOOLEAN) FALSE, StdHeader);
497
498     //7. Wait for MSRC001_0071[CurCpuFid] = MSRC001_0064[CpuFid].
499     do {
500       LibAmdMsrRead (MSR_COFVID_STS, &MsrValue, StdHeader);
501     } while (((COFVID_STS_MSR *) &MsrValue)->CurCpuFid != TempVar_d);
502
503     //8. Write 0b to MSRC001_0065[PstateEn].
504     LibAmdMsrRead (MSR_PSTATE_1, &MsrValue, StdHeader);
505     ((PSTATE_MSR *) &MsrValue)->PsEnable = 0;
506     LibAmdMsrWrite (MSR_PSTATE_1, &MsrValue, StdHeader);
507
508     //9. Write 000b to F3xDC[PstateMaxVal] and exit the sequence (no further steps are required).
509     LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
510     ((CLK_PWR_TIMING_CTRL2_REGISTER *) &LocalPciRegister)->PstateMaxVal = 0;
511     LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
512
513   } else {
514     TempVar_f = MSR_PSTATE_0;
515
516     for (k = 0; k <= PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; k++, TempVar_f++) {
517       // If pState is not disabled then do update
518       LibAmdMsrRead (TempVar_f, &MsrValue, StdHeader);
519
520       if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable == 1) {
521         Status = F10GetFrequencyXlatRegInfo (PstateCpuServices, (UINT8) k, PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].CoreFreq, &TempVar_d, &TempVar_e, &Ignored, StdHeader);
522         if (Status != AGESA_ERROR) {
523           // Bits 5:0
524           ((PSTATE_MSR *) &MsrValue)->CpuFid = TempVar_d;
525           // Bits 8:6
526           ((PSTATE_MSR *) &MsrValue)->CpuDid = TempVar_e;
527         }
528
529         // Bits 39:32
530         ((PSTATE_MSR *) &MsrValue)->IddValue = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].IddValue;
531         // Bits 41:40
532         ((PSTATE_MSR *) &MsrValue)->IddDiv = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].IddDiv;
533         // Enable the P-State
534         ((PSTATE_MSR *) &MsrValue)->PsEnable = 1;
535         LibAmdMsrWrite (TempVar_f, &MsrValue, StdHeader);
536       } else {
537         // Disable the P-State
538         ((PSTATE_MSR *) &MsrValue)->PsEnable = 0;
539         LibAmdMsrWrite (TempVar_f, &MsrValue, StdHeader);
540       }
541     }
542   }
543   return AGESA_SUCCESS;
544 }
545
546 /*---------------------------------------------------------------------------------------*/
547 /**
548  *  Family specific call to calculates the power in milliWatts of the desired P-state.
549  *
550  *  @param[in]   PstateCpuServices        Pstate CPU services.
551  *  @param[in]   StateNumber              Which P-state to analyze
552  *  @param[out]  PowerInMw                The Power in milliWatts of that P-State
553  *  @param[in]   StdHeader                Header for library and services
554  *
555  *  @retval      AGESA_SUCCESS Always succeeds.
556  */
557 AGESA_STATUS
558 F10GetPstatePower (
559   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
560   IN       UINT8 StateNumber,
561      OUT   UINT32 *PowerInMw,
562   IN       AMD_CONFIG_PARAMS *StdHeader
563   )
564 {
565   UINT32  CpuVid;
566   UINT32  IddValue;
567   UINT32  IddDiv;
568   BOOLEAN PviFlag;
569   UINT32  V_x10000;
570   UINT32  Power;
571   PCI_ADDR PciAddress;
572   UINT32  TempVar_a;
573   UINT64  LocalMsrRegister;
574
575   ASSERT (StateNumber < NM_PS_REG);
576   LibAmdMsrRead (PS_REG_BASE + (UINT32) StateNumber, &LocalMsrRegister, StdHeader);
577   ASSERT (((PSTATE_MSR *) &LocalMsrRegister)->PsEnable == 1);
578   CpuVid = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->CpuVid);
579   IddValue = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->IddValue);
580   IddDiv = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->IddDiv);
581
582   OptionMultiSocketConfiguration.GetCurrPciAddr (&PciAddress, StdHeader);
583
584   PciAddress.Address.Function = FUNC_3;
585   PciAddress.Address.Register = POWER_CTRL_MISCELLANEOUS_REG;
586   LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_a, StdHeader);
587   if ((TempVar_a & 0x00000100) != 0) {
588     PviFlag = TRUE;
589   } else {
590     PviFlag = FALSE;
591   }
592   if (PviFlag) {
593     // Set CpuVid value in case CPU is in PVI mode
594     if (CpuVid > 0x5D) {
595       CpuVid = 0x3F;
596     } else if (CpuVid > 0x3E) {
597       CpuVid = CpuVid - 0x1F;
598     } else {
599       CpuVid = (CpuVid >> 1);
600     }
601
602     // PVI Encoding
603     if (CpuVid >= 0x20) {
604       V_x10000 = 7625L - (125L * (CpuVid - 0x20));
605     } else {
606       V_x10000 = 15500L - (250L * CpuVid);
607     }
608   } else {
609     if (CpuVid >= 0x7C) {
610       V_x10000 = 0;
611     } else {
612       V_x10000 = 15500L - (125L * CpuVid);
613     }
614   }
615
616   Power = V_x10000 * IddValue;
617
618   switch (IddDiv) {
619   case 0:
620     *PowerInMw = Power / 10L;
621     break;
622   case 1:
623     *PowerInMw = Power / 100L;
624     break;
625   case 2:
626     *PowerInMw = Power / 1000L;
627     break;
628   default:
629     // IddDiv is set to an undefined value.  This is due to either a misfused CPU, or
630     // an invalid P-state MSR write.
631     ASSERT (FALSE);
632     *PowerInMw = 0;
633     break;
634   }
635   return (AGESA_SUCCESS);
636 }
637
638 /*---------------------------------------------------------------------------------------*/
639 /**
640  *  Family specific call to get CPU pstate max state.
641  *
642  *  @param[in]     PstateCpuServices      Pstate CPU services.
643  *  @param[out]    MaxPStateNumber        The max hw pstate value on the current socket.
644  *  @param[out]    NumberOfBoostStates    The number of boosted P-states on the current socket.
645  *  @param[in]     StdHeader              Handle of Header for calling lib functions and services.
646  *
647  *  @retval      AGESA_SUCCESS Always succeeds.
648  */
649 AGESA_STATUS
650 F10GetPstateMaxState (
651   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
652      OUT   UINT32              *MaxPStateNumber,
653      OUT   UINT8               *NumberOfBoostStates,
654   IN       AMD_CONFIG_PARAMS   *StdHeader
655   )
656 {
657   UINT8                NumBoostStates;
658   UINT64               MsrValue;
659
660   NumBoostStates = F10GetNumberOfBoostedPstatesOnCore (StdHeader);
661   //
662   // Read PstateMaxVal [6:4] from MSR C001_0061
663   // So, we will know the max pstate state in this socket.
664   //
665   LibAmdMsrRead (MSR_PSTATE_CURRENT_LIMIT, &MsrValue, StdHeader);
666   *MaxPStateNumber = (UINT32) (((PSTATE_CURLIM_MSR *) &MsrValue)->PstateMaxVal) + (UINT32) (NumBoostStates);
667   *NumberOfBoostStates = NumBoostStates;
668
669   return (AGESA_SUCCESS);
670 }
671
672 /*---------------------------------------------------------------------------------------*/
673 /**
674  *  Family specific call to get CPU pstate register information.
675  *
676  *  @param[in]     PstateCpuServices         Pstate CPU services.
677  *  @param[in]     PState                    Input Pstate number for query.
678  *  @param[out]    PStateEnabled             Boolean flag return pstate enable.
679  *  @param[in,out] IddVal                    Pstate current value.
680  *  @param[in,out] IddDiv                    Pstate current divisor.
681  *  @param[out]    SwPstateNumber            Software P-state number.
682  *  @param[in]     StdHeader                 Handle of Header for calling lib functions and services.
683  *
684  *  @retval      AGESA_SUCCESS Always succeeds.
685  */
686 AGESA_STATUS
687 F10GetPstateRegisterInfo (
688   IN       PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
689   IN       UINT32              PState,
690      OUT   BOOLEAN             *PStateEnabled,
691   IN OUT   UINT32              *IddVal,
692   IN OUT   UINT32              *IddDiv,
693      OUT   UINT32              *SwPstateNumber,
694   IN       AMD_CONFIG_PARAMS   *StdHeader
695   )
696 {
697   UINT8                NumBoostStates;
698   UINT64               LocalMsrRegister;
699
700   ASSERT (PState < NM_PS_REG);
701
702   // Check if CPB is supported. if yes, skip boosted p-state. The boosted p-state number = F4x15C[NumBoostStates].
703   NumBoostStates = F10GetNumberOfBoostedPstatesOnCore (StdHeader);
704
705   // Read PSTATE MSRs
706   LibAmdMsrRead (PS_REG_BASE + (UINT32) PState, &LocalMsrRegister, StdHeader);
707
708   if (PState < NumBoostStates) {
709     *SwPstateNumber = 0;
710     *PStateEnabled = FALSE;
711   } else {
712     *SwPstateNumber = PState - NumBoostStates;
713     if (((PSTATE_MSR *) &LocalMsrRegister)->PsEnable == 1) {
714       // PState enable = bit 63
715       *PStateEnabled = TRUE;
716     } else {
717       *PStateEnabled = FALSE;
718     }
719   }
720
721   // Bits 39:32 (high 32 bits [7:0])
722   *IddVal = (UINT32) ((PSTATE_MSR *) &LocalMsrRegister)->IddValue;
723   // Bits 41:40 (high 32 bits [9:8])
724   *IddDiv = (UINT32) ((PSTATE_MSR *) &LocalMsrRegister)->IddDiv;
725
726   return (AGESA_SUCCESS);
727 }
728
729 CONST PSTATE_CPU_FAMILY_SERVICES ROMDATA F10PstateServices =
730 {
731   0,
732   (PF_PSTATE_PSD_IS_NEEDED) CommonReturnTrue,
733   F10IsPstatePsdDependent,
734   F10SetTscFreqSel,
735   F10GetPstateTransLatency,
736   F10GetPstateFrequency,
737   F10PstateLevelingCoreMsrModify,
738   F10GetPstatePower,
739   F10GetPstateMaxState,
740   F10GetPstateRegisterInfo
741 };
742
743
744 /*---------------------------------------------------------------------------------------
745  *                          L O C A L    F U N C T I O N S
746  *---------------------------------------------------------------------------------------
747  */
748
749
750 /**
751  *---------------------------------------------------------------------------------------
752  *
753  *  F10GetPowerStepValueInTime
754  *
755  *  Description:
756  *    Convert power step value in time
757  *
758  *  Parameters:
759  *    @param[out]     *PowerStepPtr
760  *
761  *    @retval       VOID
762  *
763  *---------------------------------------------------------------------------------------
764  **/
765 VOID
766 STATIC
767 F10GetPowerStepValueInTime (
768   IN OUT   UINT32  *PowerStepPtr
769   )
770 {
771   UINT32 TempVar_a;
772
773   TempVar_a = *PowerStepPtr;
774
775   if (TempVar_a < 0x4) {
776     *PowerStepPtr = 400 - (TempVar_a * 100);
777   } else if (TempVar_a <  0x9) {
778     *PowerStepPtr = 130 - (TempVar_a * 10);
779   } else {
780     *PowerStepPtr = 90 - (TempVar_a * 5);
781   }
782 }
783
784
785 /**
786  *---------------------------------------------------------------------------------------
787  *
788  *  F10GetPllValueInTime
789  *
790  *  Description:
791  *    Convert PLL Value in time
792  *
793  *  Parameters:
794  *    @param[out]     *PllLockTimePtr
795  *
796  *    @retval       VOID
797  *
798  *---------------------------------------------------------------------------------------
799  **/
800 VOID
801 STATIC
802 F10GetPllValueInTime (
803   IN OUT   UINT32  *PllLockTimePtr
804   )
805 {
806   if (*PllLockTimePtr < 4) {
807     *PllLockTimePtr = *PllLockTimePtr + 1;
808   } else if (*PllLockTimePtr == 4) {
809     *PllLockTimePtr = 8;
810   } else if (*PllLockTimePtr == 5) {
811     *PllLockTimePtr = 16;
812   } else
813     *PllLockTimePtr = 0;
814 }
815
816 /*---------------------------------------------------------------------------------------*/
817 /**
818  *    This function will return the CpuFid and CpuDid in MHz, using the formula
819  *    described in the BKDG MSRC001_00[68:64] P-State [4:0] Registers:bit 8:0
820  *
821  *    @param[in]       PstateCpuServices        The current Family Specific Services.
822  *    @param[in]       PStateNumber             P-state number to check.
823  *    @param[in]       Frequency                Leveled target frequency for PStateNumber.
824  *    @param[out]      *CpuFidPtr               New leveled FID.
825  *    @param[out]      *CpuDidPtr1              New leveled DID info 1.
826  *    @param[out]      *CpuDidPtr2              New leveled DID info 2.
827  *    @param[in]       *StdHeader               Header for library and services.
828  *
829  *    @retval       AGESA_WARNING           This P-State does not need to be modified.
830  *    @retval       AGESA_SUCCESS           This P-State must be modified to be level.
831  */
832 AGESA_STATUS
833 STATIC
834 F10GetFrequencyXlatRegInfo (
835   IN       PSTATE_CPU_FAMILY_SERVICES  *PstateCpuServices,
836   IN       UINT8                  PStateNumber,
837   IN       UINT32                 Frequency,
838      OUT   UINT32                 *CpuFidPtr,
839      OUT   UINT32                 *CpuDidPtr1,
840      OUT   UINT32                 *CpuDidPtr2,
841   IN       AMD_CONFIG_PARAMS      *StdHeader
842   )
843 {
844   UINT32 i;
845   UINT32 j;
846   AGESA_STATUS Status;
847   UINT32 FrequencyInMHz;
848
849   FrequencyInMHz = 0;
850   *CpuDidPtr2 = 0xFFFF;
851
852   Status = AGESA_SUCCESS;
853
854   PstateCpuServices->GetPstateFrequency (PstateCpuServices, PStateNumber, &FrequencyInMHz, StdHeader);
855   if (FrequencyInMHz == Frequency) {
856     Status |= AGESA_WARNING;
857   }
858
859   // CPU Frequency = 100 MHz * (CpuFid + 10h) / (2^CpuDid)
860   // In this for loop i = 2^CpuDid
861
862
863   for (i = 1; i < 17; (i += i)) {
864     for (j = 0; j < 64; j++) {
865       if (Frequency == ((100 * (j + 0x10)) / i )) {
866         *CpuFidPtr = j;
867         if (i == 1) {
868           *CpuDidPtr1 = 0;
869         } else if (i == 2) {
870           *CpuDidPtr1 = 1;
871         } else if (i == 4) {
872           *CpuDidPtr1 = 2;
873         } else if (i == 8) {
874           *CpuDidPtr1 = 3;
875         } else if (i == 16) {
876           *CpuDidPtr1 = 4;
877         } else {
878           *CpuFidPtr = 0xFFFF;
879           *CpuDidPtr1 = 0xFFFF;
880         }
881         // Success
882         return Status;
883       }
884     }
885   }
886
887   // Error Condition
888   *CpuFidPtr = 0x00FF;
889   *CpuDidPtr1 = 0x00FF;
890   *CpuDidPtr2 = 0x00FF;
891
892   return AGESA_ERROR;
893 }
894