AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / Family / 0x15 / OR / F15OrIoCstate.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD Family_15 Orochi IO C-state feature support functions.
6  *
7  * Provides the functions necessary to initialize the IO C-state 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  *                             M O D U L E S    U S E D
47  *----------------------------------------------------------------------------------------
48  */
49
50 #include "AGESA.h"
51 #include "amdlib.h"
52 #include "Ids.h"
53 #include "cpuFeatures.h"
54 #include "cpuIoCstate.h"
55 #include "cpuF15PowerMgmt.h"
56 #include "cpuF15OrPowerMgmt.h"
57 #include "cpuLateInit.h"
58 #include "cpuRegisters.h"
59 #include "cpuServices.h"
60 #include "cpuApicUtilities.h"
61 #include "cpuFamilyTranslation.h"
62 #include "CommonReturns.h"
63 #include "OptionMultiSocket.h"
64 #include "Filecode.h"
65 CODE_GROUP (G3_DXE)
66 RDATA_GROUP (G3_DXE)
67 #define FILECODE PROC_CPU_FAMILY_0X15_OR_F15ORIOCSTATE_FILECODE
68
69 /*----------------------------------------------------------------------------------------
70  *           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
71  *----------------------------------------------------------------------------------------
72  */
73 VOID
74 STATIC
75 F15OrInitializeIoCstateOnCore (
76   IN       VOID *CstateBaseMsr,
77   IN       AMD_CONFIG_PARAMS *StdHeader
78   );
79
80 BOOLEAN
81 F15OrIsCsdObjGenerated (
82   IN       IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
83   IN       AMD_CONFIG_PARAMS         *StdHeader
84   );
85
86 /*----------------------------------------------------------------------------------------
87  *                   D E F I N I T I O N S    A N D    M A C R O S
88  *----------------------------------------------------------------------------------------
89  */
90 extern CPU_FAMILY_SUPPORT_TABLE            IoCstateFamilyServiceTable;
91 extern OPTION_MULTISOCKET_CONFIGURATION    OptionMultiSocketConfiguration;
92
93 /*----------------------------------------------------------------------------------------
94  *                          E X P O R T E D    F U N C T I O N S
95  *----------------------------------------------------------------------------------------
96  */
97
98 /*---------------------------------------------------------------------------------------*/
99 /**
100  *  Enable IO Cstate on a family 15h Orochi CPU.
101  *  Implement BIOS Requirements for Initialization of C-states
102  *
103  * @param[in]    IoCstateServices   Pointer to this CPU's IO Cstate family services.
104  * @param[in]    EntryPoint         Timepoint designator.
105  * @param[in]    PlatformConfig     Contains the runtime modifiable feature input data.
106  * @param[in]    StdHeader          Config Handle for library, services.
107  *
108  * @return       AGESA_SUCCESS      Always succeeds.
109  *
110  */
111 AGESA_STATUS
112 STATIC
113 F15OrInitializeIoCstate (
114   IN       IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
115   IN       UINT64                    EntryPoint,
116   IN       PLATFORM_CONFIGURATION    *PlatformConfig,
117   IN       AMD_CONFIG_PARAMS         *StdHeader
118   )
119 {
120   UINT32   LocalPciRegister;
121   UINT32   PciMask;
122   UINT64   LocalMsrRegister;
123   AP_TASK  TaskPtr;
124   PCI_ADDR PciAddress;
125
126   if ((EntryPoint & CPU_FEAT_AFTER_PM_INIT) != 0) {
127     // Initialize MSRC001_0073[CstateAddr] on each core to a region of
128     // the IO address map with 8 consecutive available addresses.
129     LocalMsrRegister = 0;
130
131     ((CSTATE_ADDRESS_MSR *) &LocalMsrRegister)->CstateAddr = PlatformConfig->CStateIoBaseAddress;
132
133     TaskPtr.FuncAddress.PfApTaskI = F15OrInitializeIoCstateOnCore;
134     TaskPtr.DataTransfer.DataSizeInDwords = 2;
135     TaskPtr.DataTransfer.DataPtr = &LocalMsrRegister;
136     TaskPtr.DataTransfer.DataTransferFlags = 0;
137     TaskPtr.ExeFlags = WAIT_FOR_CORE;
138     ApUtilRunCodeOnAllLocalCoresAtEarly (&TaskPtr, StdHeader, NULL);
139
140     // Initialize F4x128
141     // bits[0]   CoreCstateMode = 0
142     // bits[1]   CoreCstatePolicy = 0
143     // bits[4:2] HaltCstateIndex = 0
144     PciAddress.Address.Function = FUNC_4;
145     PciAddress.Address.Register = CSTATE_POLICY_CTRL1_REG;
146     LocalPciRegister = 0x00000000;
147     PciMask = 0xFFFFFFE0;
148     OptionMultiSocketConfiguration.ModifyCurrSocketPci (&PciAddress, PciMask, LocalPciRegister, StdHeader);
149   }
150   return AGESA_SUCCESS;
151 }
152
153 /*---------------------------------------------------------------------------------------*/
154 /**
155  *  Enable CState on a family 15h Orochi core.
156  *
157  * @param[in]    CstateBaseMsr      MSR value to write to C001_0073 as determined by core 0.
158  * @param[in]    StdHeader          Config Handle for library, services.
159  *
160  */
161 VOID
162 STATIC
163 F15OrInitializeIoCstateOnCore (
164   IN       VOID *CstateBaseMsr,
165   IN       AMD_CONFIG_PARAMS *StdHeader
166   )
167 {
168   // Initialize MSRC001_0073[CstateAddr] on each core
169   LibAmdMsrWrite (MSR_CSTATE_ADDRESS, (UINT64 *) CstateBaseMsr, StdHeader);
170 }
171
172 /*---------------------------------------------------------------------------------------*/
173 /**
174  *  Returns the size of CST object
175  *
176  * @param[in]    IoCstateServices   IO Cstate services.
177  * @param[in]    PlatformConfig     Contains the runtime modifiable feature input data
178  * @param[in]    StdHeader          Config Handle for library, services.
179  *
180  * @retval       CstObjSize         Size of CST Object
181  *
182  */
183 UINT32
184 STATIC
185 F15OrGetAcpiCstObj (
186   IN       IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
187   IN       PLATFORM_CONFIGURATION    *PlatformConfig,
188   IN       AMD_CONFIG_PARAMS         *StdHeader
189   )
190 {
191   BOOLEAN                   GenerateCsdObj;
192   UINT32                    CStateAcpiObjSize;
193   IO_CSTATE_FAMILY_SERVICES *FamilyServices;
194   ACPI_CST_GET_INPUT CstGetInput;
195
196   CstGetInput.IoCstateServices = IoCstateServices;
197   CstGetInput.PlatformConfig = PlatformConfig;
198   CstGetInput.CStateAcpiObjSizePtr = &CStateAcpiObjSize;
199
200   IDS_SKIP_HOOK (IDS_CST_SIZE, &CstGetInput, StdHeader) {
201     CStateAcpiObjSize = CST_HEADER_SIZE + CST_BODY_SIZE;
202
203     // If CSD Object is generated, add the size of CSD Object to the total size of
204     // CState ACPI Object size
205     GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
206     ASSERT (FamilyServices != NULL);
207     GenerateCsdObj = FamilyServices->IsCsdObjGenerated (FamilyServices, StdHeader);
208
209     if (GenerateCsdObj) {
210       CStateAcpiObjSize += CSD_HEADER_SIZE + CSD_BODY_SIZE;
211     }
212   }
213   return CStateAcpiObjSize;
214 }
215
216 /*---------------------------------------------------------------------------------------*/
217 /**
218  *  Routine to generate the C-State ACPI objects
219  *
220  * @param[in]      IoCstateServices       IO Cstate services.
221  * @param[in]      LocalApicId            Local Apic Id for each core.
222  * @param[in, out] **PstateAcpiBufferPtr  Pointer to the Acpi Buffer Pointer.
223  * @param[in]      StdHeader              Config Handle for library, services.
224  *
225  */
226 VOID
227 STATIC
228 F15OrCreateAcpiCstObj (
229   IN       IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
230   IN       UINT8                     LocalApicId,
231   IN OUT   VOID                      **PstateAcpiBufferPtr,
232   IN       AMD_CONFIG_PARAMS         *StdHeader
233   )
234 {
235   UINT64                MsrData;
236   BOOLEAN               GenerateCsdObj;
237   CST_HEADER_STRUCT     *CstHeaderPtr;
238   CST_BODY_STRUCT       *CstBodyPtr;
239   CSD_HEADER_STRUCT     *CsdHeaderPtr;
240   CSD_BODY_STRUCT       *CsdBodyPtr;
241   IO_CSTATE_FAMILY_SERVICES    *FamilyServices;
242   ACPI_CST_CREATE_INPUT  CstInput;
243
244   CstInput.IoCstateServices = IoCstateServices;
245   CstInput.LocalApicId = LocalApicId;
246   CstInput.PstateAcpiBufferPtr = PstateAcpiBufferPtr;
247
248   IDS_SKIP_HOOK (IDS_CST_CREATE, &CstInput, StdHeader) {
249     // Read from MSR C0010073 to obtain CstateAddr
250     LibAmdMsrRead (MSR_CSTATE_ADDRESS, &MsrData, StdHeader);
251
252     // Typecast the pointer
253     CstHeaderPtr = (CST_HEADER_STRUCT *) *PstateAcpiBufferPtr;
254
255     // Set CST Header
256     CstHeaderPtr->NameOpcode  = NAME_OPCODE;
257     CstHeaderPtr->CstName_a__ = CST_NAME__;
258     CstHeaderPtr->CstName_a_C = CST_NAME_C;
259     CstHeaderPtr->CstName_a_S = CST_NAME_S;
260     CstHeaderPtr->CstName_a_T = CST_NAME_T;
261
262     // Typecast the pointer
263     CstHeaderPtr++;
264     CstBodyPtr = (CST_BODY_STRUCT *) CstHeaderPtr;
265
266     // Set CST Body
267     CstBodyPtr->PkgOpcode      = PACKAGE_OPCODE;
268     CstBodyPtr->PkgLength      = CST_LENGTH;
269     CstBodyPtr->PkgElements    = CST_NUM_OF_ELEMENTS;
270     CstBodyPtr->BytePrefix     = BYTE_PREFIX_OPCODE;
271     CstBodyPtr->Count          = CST_COUNT;
272     CstBodyPtr->PkgOpcode2     = PACKAGE_OPCODE;
273     CstBodyPtr->PkgLength2     = CST_PKG_LENGTH;
274     CstBodyPtr->PkgElements2   = CST_PKG_ELEMENTS;
275     CstBodyPtr->BufferOpcode   = BUFFER_OPCODE;
276     CstBodyPtr->BufferLength   = CST_SUBPKG_LENGTH;
277     CstBodyPtr->BufferElements = CST_SUBPKG_ELEMENTS;
278     CstBodyPtr->BufferOpcode2  = BUFFER_OPCODE;
279     CstBodyPtr->GdrOpcode      = GENERIC_REG_DESCRIPTION;
280     CstBodyPtr->GdrLength      = CST_GDR_LENGTH;
281     CstBodyPtr->AddrSpaceId    = GDR_ASI_SYSTEM_IO;
282     CstBodyPtr->RegBitWidth    = 0x08;
283     CstBodyPtr->RegBitOffset   = 0x00;
284     CstBodyPtr->AddressSize    = GDR_ASZ_BYTE_ACCESS;
285     CstBodyPtr->RegisterAddr   = ((CSTATE_ADDRESS_MSR *) &MsrData)->CstateAddr + 1;
286     CstBodyPtr->EndTag         = 0x0079;
287     CstBodyPtr->BytePrefix2    = BYTE_PREFIX_OPCODE;
288     CstBodyPtr->Type           = CST_C2_TYPE;
289     CstBodyPtr->WordPrefix     = WORD_PREFIX_OPCODE;
290     CstBodyPtr->Latency        = 100;
291     CstBodyPtr->DWordPrefix    = DWORD_PREFIX_OPCODE;
292     CstBodyPtr->Power          = 0;
293
294     CstBodyPtr++;
295     //Update the pointer
296     *PstateAcpiBufferPtr = CstBodyPtr;
297
298
299   // Check whether CSD object should be generated
300     GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
301     ASSERT (FamilyServices != NULL);
302     GenerateCsdObj = FamilyServices->IsCsdObjGenerated (FamilyServices, StdHeader);
303
304     if (GenerateCsdObj) {
305       CsdHeaderPtr = (CSD_HEADER_STRUCT *) *PstateAcpiBufferPtr;
306
307       // Set CSD Header
308       CsdHeaderPtr->NameOpcode  = NAME_OPCODE;
309       CsdHeaderPtr->CsdName_a__ = CST_NAME__;
310       CsdHeaderPtr->CsdName_a_C = CST_NAME_C;
311       CsdHeaderPtr->CsdName_a_S = CST_NAME_S;
312       CsdHeaderPtr->CsdName_a_D = CSD_NAME_D;
313
314       CsdHeaderPtr++;
315       CsdBodyPtr = (CSD_BODY_STRUCT *) CsdHeaderPtr;
316
317       // Set CSD Body
318       CsdBodyPtr->PkgOpcode         = PACKAGE_OPCODE;
319       CsdBodyPtr->PkgLength         = CSD_BODY_SIZE - 1;
320       CsdBodyPtr->PkgElements       = 1;
321       CsdBodyPtr->PkgOpcode2        = PACKAGE_OPCODE;
322       CsdBodyPtr->PkgLength2        = CSD_BODY_SIZE - 4; // CSD_BODY_SIZE - Package() - Package Opcode
323       CsdBodyPtr->PkgElements2      = 6;
324       CsdBodyPtr->BytePrefix        = BYTE_PREFIX_OPCODE;
325       CsdBodyPtr->NumEntries        = 6;
326       CsdBodyPtr->BytePrefix2       = BYTE_PREFIX_OPCODE;
327       CsdBodyPtr->Revision          = 0;
328       CsdBodyPtr->DWordPrefix       = DWORD_PREFIX_OPCODE;
329       CsdBodyPtr->Domain            = (LocalApicId & 0xFE) >> 1;
330       CsdBodyPtr->DWordPrefix2      = DWORD_PREFIX_OPCODE;
331       CsdBodyPtr->CoordType         = CSD_COORD_TYPE_HW_ALL;
332       CsdBodyPtr->DWordPrefix3      = DWORD_PREFIX_OPCODE;
333       CsdBodyPtr->NumProcessors     = 0x2;
334       CsdBodyPtr->DWordPrefix4      = DWORD_PREFIX_OPCODE;
335       CsdBodyPtr->Index             = 0x0;
336
337       CsdBodyPtr++;
338
339       // Update the pointer
340       *PstateAcpiBufferPtr = CsdBodyPtr;
341     }
342   }
343 }
344
345 /*---------------------------------------------------------------------------------------*/
346 /**
347  * Routine to check whether CSD object should be created.
348  *
349  * @param[in]      IoCstateServices      IO Cstate services.
350  * @param[in]      StdHeader             Config Handle for library, services.
351  *
352  * @retval         TRUE                  CSD Object should be created.
353  * @retval         FALSE                 CSD Object should not be created.
354  *
355  */
356 BOOLEAN
357 F15OrIsCsdObjGenerated (
358   IN       IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
359   IN       AMD_CONFIG_PARAMS         *StdHeader
360   )
361 {
362   // CSD Object should only be created when there are two cores per compute unit
363   if (GetComputeUnitMapping (StdHeader) == EvenCoresMapping) {
364     return TRUE;
365   }
366   return FALSE;
367 }
368
369 CONST IO_CSTATE_FAMILY_SERVICES ROMDATA F15OrIoCstateSupport =
370 {
371   0,
372   (PF_IO_CSTATE_IS_SUPPORTED) CommonReturnTrue,
373   F15OrInitializeIoCstate,
374   F15OrGetAcpiCstObj,
375   F15OrCreateAcpiCstObj,
376   F15OrIsCsdObjGenerated
377 };