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