3 Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
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
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Protocol/ArmScmiPerformanceProtocol.h>
16 #include "ArmScmiPerformanceProtocolPrivate.h"
17 #include "ScmiPrivate.h"
19 /** Return version of the performance management protocol supported by SCP.
22 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
24 @param[out] Version Version of the supported SCMI performance management
27 @retval EFI_SUCCESS The version is returned.
28 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
29 @retval !(EFI_SUCCESS) Other errors.
33 PerformanceGetVersion (
34 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
38 return ScmiGetProtocolVersion (ScmiProtocolIdPerformance
, Version
);
41 /** Return protocol attributes of the performance management protocol.
43 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
45 @param[out] Attributes Protocol attributes.
47 @retval EFI_SUCCESS Protocol attributes are returned.
48 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
49 @retval !(EFI_SUCCESS) Other errors.
53 PerformanceGetAttributes (
54 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
55 OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES
*Attributes
61 Status
= ScmiGetProtocolAttributes (
62 ScmiProtocolIdPerformance
,
65 if (EFI_ERROR (Status
)) {
72 sizeof (SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES
)
78 /** Return performance domain attributes.
80 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
81 @param[in] DomainId Identifier for the performance domain.
83 @param[out] Attributes Performance domain attributes.
85 @retval EFI_SUCCESS Domain attributes are returned.
86 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
87 @retval !(EFI_SUCCESS) Other errors.
91 PerformanceDomainAttributes (
92 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
94 OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES
*DomainAttributes
98 UINT32
*MessageParams
;
100 UINT32 PayloadLength
;
103 Status
= ScmiCommandGetPayload (&MessageParams
);
104 if (EFI_ERROR (Status
)) {
108 *MessageParams
= DomainId
;
110 Cmd
.ProtocolId
= ScmiProtocolIdPerformance
;
111 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_DOMAIN_ATTRIBUTES
;
113 PayloadLength
= sizeof (DomainId
);
115 Status
= ScmiCommandExecute (
120 if (EFI_ERROR (Status
)) {
127 sizeof (SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES
)
133 /** Return list of performance domain levels of a given domain.
135 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
136 @param[in] DomainId Identifier for the performance domain.
138 @param[out] NumLevels Total number of levels a domain can support.
140 @param[in,out] LevelArraySize Size of the performance level array.
142 @param[out] LevelArray Array of the performance levels.
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.
152 PerformanceDescribeLevels (
153 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
155 OUT UINT32
*NumLevels
,
156 IN OUT UINT32
*LevelArraySize
,
157 OUT SCMI_PERFORMANCE_LEVEL
*LevelArray
161 UINT32 PayloadLength
;
163 UINT32
* MessageParams
;
167 UINT32 ReturnNumLevels
;
168 UINT32 ReturnRemainNumLevels
;
170 PERF_DESCRIBE_LEVELS
*Levels
;
172 Status
= ScmiCommandGetPayload (&MessageParams
);
173 if (EFI_ERROR (Status
)) {
180 *MessageParams
++ = DomainId
;
182 Cmd
.ProtocolId
= ScmiProtocolIdPerformance
;
183 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS
;
187 *MessageParams
= LevelIndex
;
189 // Note, PayloadLength is an IN/OUT parameter.
190 PayloadLength
= sizeof (DomainId
) + sizeof (LevelIndex
);
192 Status
= ScmiCommandExecute (
197 if (EFI_ERROR (Status
)) {
201 ReturnNumLevels
= NUM_PERF_LEVELS (Levels
->NumLevels
);
202 ReturnRemainNumLevels
= NUM_REMAIN_PERF_LEVELS (Levels
->NumLevels
);
204 if (RequiredSize
== 0) {
205 *NumLevels
= ReturnNumLevels
+ ReturnRemainNumLevels
;
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
;
215 for (LevelNo
= 0; LevelNo
< ReturnNumLevels
; LevelNo
++) {
217 &LevelArray
[LevelIndex
++],
218 &Levels
->PerfLevel
[LevelNo
],
219 sizeof (SCMI_PERFORMANCE_LEVEL
)
223 } while (ReturnRemainNumLevels
!= 0);
225 *LevelArraySize
= RequiredSize
;
230 /** Set performance limits of a domain.
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.
236 @retval EFI_SUCCESS Performance limits set successfully.
237 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
238 @retval !(EFI_SUCCESS) Other errors.
241 PerformanceLimitsSet (
242 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
244 IN SCMI_PERFORMANCE_LIMITS
*Limits
248 UINT32 PayloadLength
;
250 UINT32
*MessageParams
;
252 Status
= ScmiCommandGetPayload (&MessageParams
);
253 if (EFI_ERROR (Status
)) {
257 *MessageParams
++ = DomainId
;
258 *MessageParams
++ = Limits
->RangeMax
;
259 *MessageParams
= Limits
->RangeMin
;
261 Cmd
.ProtocolId
= ScmiProtocolIdPerformance
;
262 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET
;
264 PayloadLength
= sizeof (DomainId
) + sizeof (SCMI_PERFORMANCE_LIMITS
);
266 Status
= ScmiCommandExecute (
275 /** Get performance limits of a domain.
277 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
278 @param[in] DomainId Identifier for the performance domain.
280 @param[out] Limit Performance Limits of the domain.
282 @retval EFI_SUCCESS Performance limits are returned.
283 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
284 @retval !(EFI_SUCCESS) Other errors.
287 PerformanceLimitsGet (
288 SCMI_PERFORMANCE_PROTOCOL
*This
,
290 SCMI_PERFORMANCE_LIMITS
*Limits
294 UINT32 PayloadLength
;
296 UINT32
*MessageParams
;
298 SCMI_PERFORMANCE_LIMITS
*ReturnValues
;
300 Status
= ScmiCommandGetPayload (&MessageParams
);
301 if (EFI_ERROR (Status
)) {
305 *MessageParams
= DomainId
;
307 Cmd
.ProtocolId
= ScmiProtocolIdPerformance
;
308 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET
;
310 PayloadLength
= sizeof (DomainId
);
312 Status
= ScmiCommandExecute (
315 (UINT32
**)&ReturnValues
317 if (EFI_ERROR (Status
)) {
321 Limits
->RangeMax
= ReturnValues
->RangeMax
;
322 Limits
->RangeMin
= ReturnValues
->RangeMin
;
327 /** Set performance level of a domain.
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.
333 @retval EFI_SUCCESS Performance level set successfully.
334 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
335 @retval !(EFI_SUCCESS) Other errors.
338 PerformanceLevelSet (
339 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
345 UINT32 PayloadLength
;
347 UINT32
*MessageParams
;
349 Status
= ScmiCommandGetPayload (&MessageParams
);
350 if (EFI_ERROR (Status
)) {
354 *MessageParams
++ = DomainId
;
355 *MessageParams
= Level
;
357 Cmd
.ProtocolId
= ScmiProtocolIdPerformance
;
358 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET
;
360 PayloadLength
= sizeof (DomainId
) + sizeof (Level
);
362 Status
= ScmiCommandExecute (
371 /** Get performance level of a domain.
373 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
374 @param[in] DomainId Identifier for the performance domain.
376 @param[out] Level Performance level of the domain.
378 @retval EFI_SUCCESS Performance level got successfully.
379 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
380 @retval !(EFI_SUCCESS) Other errors.
383 PerformanceLevelGet (
384 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
390 UINT32 PayloadLength
;
392 UINT32
*ReturnValues
;
393 UINT32
*MessageParams
;
395 Status
= ScmiCommandGetPayload (&MessageParams
);
396 if (EFI_ERROR (Status
)) {
400 *MessageParams
= DomainId
;
402 Cmd
.ProtocolId
= ScmiProtocolIdPerformance
;
403 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET
;
405 PayloadLength
= sizeof (DomainId
);
407 Status
= ScmiCommandExecute (
412 if (EFI_ERROR (Status
)) {
416 *Level
= *ReturnValues
;
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
,
433 /** Initialize performance management protocol and install on a given Handle.
435 @param[in] Handle Handle to install performance management
438 @retval EFI_SUCCESS Performance protocol installed successfully.
441 ScmiPerformanceProtocolInit (
442 IN EFI_HANDLE
* Handle
445 return gBS
->InstallMultipleProtocolInterfaces (
447 &gArmScmiPerformanceProtocolGuid
,
448 &PerformanceProtocol
,