]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
ArmPkg: Fix Ecc error 8005 for SCMI_PROTOCOL_ID
[mirror_edk2.git] / ArmPkg / Drivers / ArmScmiDxe / ScmiPerformanceProtocol.c
1 /** @file
2
3 Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 System Control and Management Interface V1.0
8 http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
9 DEN0056A_System_Control_and_Management_Interface.pdf
10 **/
11
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Protocol/ArmScmiPerformanceProtocol.h>
15
16 #include "ArmScmiPerformanceProtocolPrivate.h"
17 #include "ScmiPrivate.h"
18
19 /** Return version of the performance management protocol supported by SCP.
20 firmware.
21
22 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
23
24 @param[out] Version Version of the supported SCMI performance management
25 protocol.
26
27 @retval EFI_SUCCESS The version is returned.
28 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
29 @retval !(EFI_SUCCESS) Other errors.
30 **/
31 STATIC
32 EFI_STATUS
33 PerformanceGetVersion (
34 IN SCMI_PERFORMANCE_PROTOCOL *This,
35 OUT UINT32 *Version
36 )
37 {
38 return ScmiGetProtocolVersion (ScmiProtocolIdPerformance, Version);
39 }
40
41 /** Return protocol attributes of the performance management protocol.
42
43 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
44
45 @param[out] Attributes Protocol attributes.
46
47 @retval EFI_SUCCESS Protocol attributes are returned.
48 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
49 @retval !(EFI_SUCCESS) Other errors.
50 **/
51 STATIC
52 EFI_STATUS
53 PerformanceGetAttributes (
54 IN SCMI_PERFORMANCE_PROTOCOL *This,
55 OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES *Attributes
56 )
57 {
58 EFI_STATUS Status;
59 UINT32* ReturnValues;
60
61 Status = ScmiGetProtocolAttributes (
62 ScmiProtocolIdPerformance,
63 &ReturnValues
64 );
65 if (EFI_ERROR (Status)) {
66 return Status;
67 }
68
69 CopyMem (
70 Attributes,
71 ReturnValues,
72 sizeof (SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES)
73 );
74
75 return EFI_SUCCESS;
76 }
77
78 /** Return performance domain attributes.
79
80 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
81 @param[in] DomainId Identifier for the performance domain.
82
83 @param[out] Attributes Performance domain attributes.
84
85 @retval EFI_SUCCESS Domain attributes are returned.
86 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
87 @retval !(EFI_SUCCESS) Other errors.
88 **/
89 STATIC
90 EFI_STATUS
91 PerformanceDomainAttributes (
92 IN SCMI_PERFORMANCE_PROTOCOL *This,
93 IN UINT32 DomainId,
94 OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES *DomainAttributes
95 )
96 {
97 EFI_STATUS Status;
98 UINT32 *MessageParams;
99 UINT32 *ReturnValues;
100 UINT32 PayloadLength;
101 SCMI_COMMAND Cmd;
102
103 Status = ScmiCommandGetPayload (&MessageParams);
104 if (EFI_ERROR (Status)) {
105 return Status;
106 }
107
108 *MessageParams = DomainId;
109
110 Cmd.ProtocolId = ScmiProtocolIdPerformance;
111 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_DOMAIN_ATTRIBUTES;
112
113 PayloadLength = sizeof (DomainId);
114
115 Status = ScmiCommandExecute (
116 &Cmd,
117 &PayloadLength,
118 &ReturnValues
119 );
120 if (EFI_ERROR (Status)) {
121 return Status;
122 }
123
124 CopyMem (
125 DomainAttributes,
126 ReturnValues,
127 sizeof (SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES)
128 );
129
130 return EFI_SUCCESS;
131 }
132
133 /** Return list of performance domain levels of a given domain.
134
135 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
136 @param[in] DomainId Identifier for the performance domain.
137
138 @param[out] NumLevels Total number of levels a domain can support.
139
140 @param[in,out] LevelArraySize Size of the performance level array.
141
142 @param[out] LevelArray Array of the performance levels.
143
144 @retval EFI_SUCCESS Domain levels are returned.
145 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
146 @retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result.
147 It has been updated to the size needed.
148 @retval !(EFI_SUCCESS) Other errors.
149 **/
150 STATIC
151 EFI_STATUS
152 PerformanceDescribeLevels (
153 IN SCMI_PERFORMANCE_PROTOCOL *This,
154 IN UINT32 DomainId,
155 OUT UINT32 *NumLevels,
156 IN OUT UINT32 *LevelArraySize,
157 OUT SCMI_PERFORMANCE_LEVEL *LevelArray
158 )
159 {
160 EFI_STATUS Status;
161 UINT32 PayloadLength;
162 SCMI_COMMAND Cmd;
163 UINT32* MessageParams;
164 UINT32 LevelIndex;
165 UINT32 RequiredSize;
166 UINT32 LevelNo;
167 UINT32 ReturnNumLevels;
168 UINT32 ReturnRemainNumLevels;
169
170 PERF_DESCRIBE_LEVELS *Levels;
171
172 Status = ScmiCommandGetPayload (&MessageParams);
173 if (EFI_ERROR (Status)) {
174 return Status;
175 }
176
177 LevelIndex = 0;
178 RequiredSize = 0;
179
180 *MessageParams++ = DomainId;
181
182 Cmd.ProtocolId = ScmiProtocolIdPerformance;
183 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS;
184
185 do {
186
187 *MessageParams = LevelIndex;
188
189 // Note, PayloadLength is an IN/OUT parameter.
190 PayloadLength = sizeof (DomainId) + sizeof (LevelIndex);
191
192 Status = ScmiCommandExecute (
193 &Cmd,
194 &PayloadLength,
195 (UINT32**)&Levels
196 );
197 if (EFI_ERROR (Status)) {
198 return Status;
199 }
200
201 ReturnNumLevels = NUM_PERF_LEVELS (Levels->NumLevels);
202 ReturnRemainNumLevels = NUM_REMAIN_PERF_LEVELS (Levels->NumLevels);
203
204 if (RequiredSize == 0) {
205 *NumLevels = ReturnNumLevels + ReturnRemainNumLevels;
206
207 RequiredSize = (*NumLevels) * sizeof (SCMI_PERFORMANCE_LEVEL);
208 if (RequiredSize > (*LevelArraySize)) {
209 // Update LevelArraySize with required size.
210 *LevelArraySize = RequiredSize;
211 return EFI_BUFFER_TOO_SMALL;
212 }
213 }
214
215 for (LevelNo = 0; LevelNo < ReturnNumLevels; LevelNo++) {
216 CopyMem (
217 &LevelArray[LevelIndex++],
218 &Levels->PerfLevel[LevelNo],
219 sizeof (SCMI_PERFORMANCE_LEVEL)
220 );
221 }
222
223 } while (ReturnRemainNumLevels != 0);
224
225 *LevelArraySize = RequiredSize;
226
227 return EFI_SUCCESS;
228 }
229
230 /** Set performance limits of a domain.
231
232 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
233 @param[in] DomainId Identifier for the performance domain.
234 @param[in] Limit Performance limit to set.
235
236 @retval EFI_SUCCESS Performance limits set successfully.
237 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
238 @retval !(EFI_SUCCESS) Other errors.
239 **/
240 EFI_STATUS
241 PerformanceLimitsSet (
242 IN SCMI_PERFORMANCE_PROTOCOL *This,
243 IN UINT32 DomainId,
244 IN SCMI_PERFORMANCE_LIMITS *Limits
245 )
246 {
247 EFI_STATUS Status;
248 UINT32 PayloadLength;
249 SCMI_COMMAND Cmd;
250 UINT32 *MessageParams;
251
252 Status = ScmiCommandGetPayload (&MessageParams);
253 if (EFI_ERROR (Status)) {
254 return Status;
255 }
256
257 *MessageParams++ = DomainId;
258 *MessageParams++ = Limits->RangeMax;
259 *MessageParams = Limits->RangeMin;
260
261 Cmd.ProtocolId = ScmiProtocolIdPerformance;
262 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET;
263
264 PayloadLength = sizeof (DomainId) + sizeof (SCMI_PERFORMANCE_LIMITS);
265
266 Status = ScmiCommandExecute (
267 &Cmd,
268 &PayloadLength,
269 NULL
270 );
271
272 return Status;
273 }
274
275 /** Get performance limits of a domain.
276
277 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
278 @param[in] DomainId Identifier for the performance domain.
279
280 @param[out] Limit Performance Limits of the domain.
281
282 @retval EFI_SUCCESS Performance limits are returned.
283 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
284 @retval !(EFI_SUCCESS) Other errors.
285 **/
286 EFI_STATUS
287 PerformanceLimitsGet (
288 SCMI_PERFORMANCE_PROTOCOL *This,
289 UINT32 DomainId,
290 SCMI_PERFORMANCE_LIMITS *Limits
291 )
292 {
293 EFI_STATUS Status;
294 UINT32 PayloadLength;
295 SCMI_COMMAND Cmd;
296 UINT32 *MessageParams;
297
298 SCMI_PERFORMANCE_LIMITS *ReturnValues;
299
300 Status = ScmiCommandGetPayload (&MessageParams);
301 if (EFI_ERROR (Status)) {
302 return Status;
303 }
304
305 *MessageParams = DomainId;
306
307 Cmd.ProtocolId = ScmiProtocolIdPerformance;
308 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET;
309
310 PayloadLength = sizeof (DomainId);
311
312 Status = ScmiCommandExecute (
313 &Cmd,
314 &PayloadLength,
315 (UINT32**)&ReturnValues
316 );
317 if (EFI_ERROR (Status)) {
318 return Status;
319 }
320
321 Limits->RangeMax = ReturnValues->RangeMax;
322 Limits->RangeMin = ReturnValues->RangeMin;
323
324 return EFI_SUCCESS;
325 }
326
327 /** Set performance level of a domain.
328
329 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
330 @param[in] DomainId Identifier for the performance domain.
331 @param[in] Level Performance level of the domain.
332
333 @retval EFI_SUCCESS Performance level set successfully.
334 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
335 @retval !(EFI_SUCCESS) Other errors.
336 **/
337 EFI_STATUS
338 PerformanceLevelSet (
339 IN SCMI_PERFORMANCE_PROTOCOL *This,
340 IN UINT32 DomainId,
341 IN UINT32 Level
342 )
343 {
344 EFI_STATUS Status;
345 UINT32 PayloadLength;
346 SCMI_COMMAND Cmd;
347 UINT32 *MessageParams;
348
349 Status = ScmiCommandGetPayload (&MessageParams);
350 if (EFI_ERROR (Status)) {
351 return Status;
352 }
353
354 *MessageParams++ = DomainId;
355 *MessageParams = Level;
356
357 Cmd.ProtocolId = ScmiProtocolIdPerformance;
358 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET;
359
360 PayloadLength = sizeof (DomainId) + sizeof (Level);
361
362 Status = ScmiCommandExecute (
363 &Cmd,
364 &PayloadLength,
365 NULL
366 );
367
368 return Status;
369 }
370
371 /** Get performance level of a domain.
372
373 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
374 @param[in] DomainId Identifier for the performance domain.
375
376 @param[out] Level Performance level of the domain.
377
378 @retval EFI_SUCCESS Performance level got successfully.
379 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
380 @retval !(EFI_SUCCESS) Other errors.
381 **/
382 EFI_STATUS
383 PerformanceLevelGet (
384 IN SCMI_PERFORMANCE_PROTOCOL *This,
385 IN UINT32 DomainId,
386 OUT UINT32 *Level
387 )
388 {
389 EFI_STATUS Status;
390 UINT32 PayloadLength;
391 SCMI_COMMAND Cmd;
392 UINT32 *ReturnValues;
393 UINT32 *MessageParams;
394
395 Status = ScmiCommandGetPayload (&MessageParams);
396 if (EFI_ERROR (Status)) {
397 return Status;
398 }
399
400 *MessageParams = DomainId;
401
402 Cmd.ProtocolId = ScmiProtocolIdPerformance;
403 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET;
404
405 PayloadLength = sizeof (DomainId);
406
407 Status = ScmiCommandExecute (
408 &Cmd,
409 &PayloadLength,
410 &ReturnValues
411 );
412 if (EFI_ERROR (Status)) {
413 return Status;
414 }
415
416 *Level = *ReturnValues;
417
418 return EFI_SUCCESS;
419 }
420
421 // Instance of the SCMI performance management protocol.
422 STATIC CONST SCMI_PERFORMANCE_PROTOCOL PerformanceProtocol = {
423 PerformanceGetVersion,
424 PerformanceGetAttributes,
425 PerformanceDomainAttributes,
426 PerformanceDescribeLevels,
427 PerformanceLimitsSet,
428 PerformanceLimitsGet,
429 PerformanceLevelSet,
430 PerformanceLevelGet
431 };
432
433 /** Initialize performance management protocol and install on a given Handle.
434
435 @param[in] Handle Handle to install performance management
436 protocol.
437
438 @retval EFI_SUCCESS Performance protocol installed successfully.
439 **/
440 EFI_STATUS
441 ScmiPerformanceProtocolInit (
442 IN EFI_HANDLE* Handle
443 )
444 {
445 return gBS->InstallMultipleProtocolInterfaces (
446 Handle,
447 &gArmScmiPerformanceProtocolGuid,
448 &PerformanceProtocol,
449 NULL
450 );
451 }