TianoCore EDK2 master
Loading...
Searching...
No Matches
DynamicTablesScmiInfoLib.c
Go to the documentation of this file.
1
12#include <Library/AcpiLib.h>
14#include <Library/DebugLib.h>
17#include <Protocol/ArmScmi.h>
19
25#define ARM_FFH_DELIVERED_PERF_COUNTER_REGISTER 0x0
26#define ARM_FFH_REFERENCE_PERF_COUNTER_REGISTER 0x1
27
30
44EFIAPI
46 IN EFI_HANDLE ImageHandle,
47 IN EFI_SYSTEM_TABLE *SystemTable
48 )
49{
50 EFI_STATUS Status;
51 UINT32 Version;
52
53 Status = gBS->LocateProtocol (
54 &gArmScmiPerformanceProtocolGuid,
55 NULL,
56 (VOID **)&ScmiPerfProtocol
57 );
58 if (EFI_ERROR (Status)) {
59 return Status;
60 }
61
62 Status = ScmiPerfProtocol->GetVersion (ScmiPerfProtocol, &Version);
63 if (EFI_ERROR (Status)) {
64 return Status;
65 }
66
67 // FastChannels were added in SCMI v2.0 spec.
68 if (Version < PERFORMANCE_PROTOCOL_VERSION_V2) {
69 DEBUG ((
70 DEBUG_ERROR,
71 "DynamicTablesScmiInfoLib requires SCMI version > 2.0\n"
72 ));
73 return EFI_UNSUPPORTED;
74 }
75
76 return Status;
77}
78
100EFIAPI
102 IN UINT32 DomainId,
103 OUT SCMI_PERFORMANCE_LEVEL **LevelArray,
104 OUT UINT32 *LevelArrayCount
105 )
106{
107 EFI_STATUS Status;
109 UINT32 Count;
110 UINT32 Size;
111
112 if ((ScmiPerfProtocol == NULL) ||
113 (LevelArray == NULL) ||
114 (LevelArrayCount == NULL))
115 {
116 return EFI_INVALID_PARAMETER;
117 }
118
119 // First call to get the number of levels.
120 Size = 0;
121 Status = ScmiPerfProtocol->DescribeLevels (
123 DomainId,
124 &Count,
125 &Size,
126 NULL
127 );
128 if (Status != EFI_BUFFER_TOO_SMALL) {
129 // EFI_SUCCESS is not a valid option.
130 if (Status == EFI_SUCCESS) {
131 return EFI_INVALID_PARAMETER;
132 } else {
133 return Status;
134 }
135 }
136
137 Array = AllocateZeroPool (Size);
138 if (Array == NULL) {
139 return EFI_OUT_OF_RESOURCES;
140 }
141
142 // Second call to get the descriptions of the levels.
143 Status = ScmiPerfProtocol->DescribeLevels (
145 DomainId,
146 &Count,
147 &Size,
148 Array
149 );
150 if (EFI_ERROR (Status)) {
151 return Status;
152 }
153
154 *LevelArray = Array;
155 *LevelArrayCount = Count;
156
157 return Status;
158}
159
173EFIAPI
175 IN UINT32 DomainId,
176 OUT AML_CPC_INFO *CpcInfo
177 )
178{
179 EFI_STATUS Status;
182 SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES DomainAttributes;
183
184 SCMI_PERFORMANCE_LEVEL *LevelArray;
185 UINT32 LevelCount;
186
187 UINT64 FcLevelGetAddr;
188 UINT64 FcLimitsMaxSetAddr;
189 UINT64 FcLimitsMinSetAddr;
190
191 if ((ScmiPerfProtocol == NULL) ||
192 (CpcInfo == NULL))
193 {
194 return EFI_INVALID_PARAMETER;
195 }
196
197 Status = ScmiPerfProtocol->DescribeFastchannel (
199 DomainId,
200 ScmiMessageIdPerformanceLevelSet,
201 &FcLevelGet
202 );
203 if (EFI_ERROR (Status)) {
204 return Status;
205 }
206
207 Status = ScmiPerfProtocol->DescribeFastchannel (
209 DomainId,
210 ScmiMessageIdPerformanceLimitsSet,
211 &FcLimitsSet
212 );
213 if (EFI_ERROR (Status)) {
214 return Status;
215 }
216
217 Status = ScmiPerfProtocol->GetDomainAttributes (
219 DomainId,
220 &DomainAttributes
221 );
222 if (EFI_ERROR (Status)) {
223 return Status;
224 }
225
226 Status = DynamicTablesScmiInfoDescribeLevels (DomainId, &LevelArray, &LevelCount);
227 if (EFI_ERROR (Status)) {
228 return Status;
229 }
230
231 /* Do some safety checks.
232 Only support FastChannels (and not doorbells) as this is
233 the only mechanism supported by SCP.
234 FcLimits[Get|Set] require 2 UINT32 values (max, then min) and
235 FcLimits[Get|Set] require 1 UINT32 value (level).
236 */
237 if ((FcLevelGet.ChanSize != sizeof (UINT32)) ||
240 (FcLimitsSet.ChanSize != 2 * sizeof (UINT32)) ||
243 {
244 Status = EFI_INVALID_PARAMETER;
245 goto exit_handler;
246 }
247
248 FcLevelGetAddr = ((UINT64)FcLevelGet.ChanAddrHigh << 32) |
249 FcLevelGet.ChanAddrLow;
250 FcLimitsMaxSetAddr = ((UINT64)FcLimitsSet.ChanAddrHigh << 32) |
251 FcLimitsSet.ChanAddrLow;
252 FcLimitsMinSetAddr = FcLimitsMaxSetAddr + 0x4;
253
254 CpcInfo->Revision = EFI_ACPI_6_5_AML_CPC_REVISION;
255 CpcInfo->HighestPerformanceInteger = LevelArray[LevelCount - 1].Level;
256 CpcInfo->NominalPerformanceInteger = DomainAttributes.SustainedPerfLevel;
257 CpcInfo->LowestNonlinearPerformanceInteger = LevelArray[0].Level;
258 CpcInfo->LowestPerformanceInteger = LevelArray[0].Level;
259
260 CpcInfo->DesiredPerformanceRegister.AddressSpaceId = EFI_ACPI_6_5_SYSTEM_MEMORY;
261 CpcInfo->DesiredPerformanceRegister.RegisterBitWidth = 32;
262 CpcInfo->DesiredPerformanceRegister.RegisterBitOffset = 0;
263 CpcInfo->DesiredPerformanceRegister.AccessSize = EFI_ACPI_6_5_DWORD;
264 CpcInfo->DesiredPerformanceRegister.Address = FcLevelGetAddr;
265
266 CpcInfo->MinimumPerformanceRegister.AddressSpaceId = EFI_ACPI_6_5_SYSTEM_MEMORY;
267 CpcInfo->MinimumPerformanceRegister.RegisterBitWidth = 32;
268 CpcInfo->MinimumPerformanceRegister.RegisterBitOffset = 0;
269 CpcInfo->MinimumPerformanceRegister.AccessSize = EFI_ACPI_6_5_DWORD;
270 CpcInfo->MinimumPerformanceRegister.Address = FcLimitsMinSetAddr;
271
272 CpcInfo->MaximumPerformanceRegister.AddressSpaceId = EFI_ACPI_6_5_SYSTEM_MEMORY;
273 CpcInfo->MaximumPerformanceRegister.RegisterBitWidth = 32;
274 CpcInfo->MaximumPerformanceRegister.RegisterBitOffset = 0;
275 CpcInfo->MaximumPerformanceRegister.AccessSize = EFI_ACPI_6_5_DWORD;
276 CpcInfo->MaximumPerformanceRegister.Address = FcLimitsMaxSetAddr;
277
278 CpcInfo->ReferencePerformanceCounterRegister.AddressSpaceId = EFI_ACPI_6_5_FUNCTIONAL_FIXED_HARDWARE;
279 CpcInfo->ReferencePerformanceCounterRegister.RegisterBitWidth = 0x40;
280 CpcInfo->ReferencePerformanceCounterRegister.RegisterBitOffset = 0;
281 CpcInfo->ReferencePerformanceCounterRegister.AccessSize = ARM_FFH_REFERENCE_PERF_COUNTER_REGISTER;
282 CpcInfo->ReferencePerformanceCounterRegister.Address = 0x4;
283
284 CpcInfo->DeliveredPerformanceCounterRegister.AddressSpaceId = EFI_ACPI_6_5_FUNCTIONAL_FIXED_HARDWARE;
285 CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitWidth = 0x40;
286 CpcInfo->DeliveredPerformanceCounterRegister.RegisterBitOffset = 0;
287 CpcInfo->DeliveredPerformanceCounterRegister.AccessSize = ARM_FFH_DELIVERED_PERF_COUNTER_REGISTER;
288 CpcInfo->DeliveredPerformanceCounterRegister.Address = 0x4;
289
290 // SCMI should advertise performance values on a unified scale. So frequency
291 // values are not available. LowestFrequencyInteger and
292 // NominalFrequencyInteger are populated in the ConfigurationManager.
293
294exit_handler:
295 FreePool (LevelArray);
296 return Status;
297}
#define EFI_ACPI_6_5_AML_CPC_REVISION
Definition: Acpi65.h:29
#define SCMI_PERF_FC_ATTRIB_HAS_DOORBELL
Doorbell Support bit.
STATIC EFI_STATUS EFIAPI DynamicTablesScmiInfoDescribeLevels(IN UINT32 DomainId, OUT SCMI_PERFORMANCE_LEVEL **LevelArray, OUT UINT32 *LevelArrayCount)
EFI_STATUS EFIAPI DynamicTablesScmiInfoGetFastChannel(IN UINT32 DomainId, OUT AML_CPC_INFO *CpcInfo)
STATIC SCMI_PERFORMANCE_PROTOCOL * ScmiPerfProtocol
Arm SCMI performance protocol.
#define ARM_FFH_DELIVERED_PERF_COUNTER_REGISTER
EFI_STATUS EFIAPI DynamicTablesScmiInfoLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
Performance protocol describe fastchannel.
UINT32 ChanAddrHigh
Higher 32 bits of the FastChannel address.
UINT32 ChanAddrLow
Lower 32 bits of the FastChannel address.
UINT32 ChanSize
Size of the FastChannel in bytes.