3 Copyright (c) 2017-2018, Arm Limited. All rights reserved.
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 System Control and Management Interface V1.0
14 http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
15 DEN0056A_System_Control_and_Management_Interface.pdf
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Protocol/ArmScmiPerformanceProtocol.h>
22 #include "ArmScmiPerformanceProtocolPrivate.h"
23 #include "ScmiPrivate.h"
25 /** Return version of the performance management protocol supported by SCP.
28 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
30 @param[out] Version Version of the supported SCMI performance management
33 @retval EFI_SUCCESS The version is returned.
34 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
35 @retval !(EFI_SUCCESS) Other errors.
39 PerformanceGetVersion (
40 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
44 return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_PERFORMANCE
, Version
);
47 /** Return protocol attributes of the performance management protocol.
49 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
51 @param[out] Attributes Protocol attributes.
53 @retval EFI_SUCCESS Protocol attributes are returned.
54 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
55 @retval !(EFI_SUCCESS) Other errors.
59 PerformanceGetAttributes (
60 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
61 OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES
*Attributes
67 Status
= ScmiGetProtocolAttributes (
68 SCMI_PROTOCOL_ID_PERFORMANCE
,
71 if (EFI_ERROR (Status
)) {
78 sizeof (SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES
)
84 /** Return performance domain attributes.
86 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
87 @param[in] DomainId Identifier for the performance domain.
89 @param[out] Attributes Performance domain attributes.
91 @retval EFI_SUCCESS Domain attributes are returned.
92 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
93 @retval !(EFI_SUCCESS) Other errors.
97 PerformanceDomainAttributes (
98 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
100 OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES
*DomainAttributes
104 UINT32
*MessageParams
;
105 UINT32
*ReturnValues
;
106 UINT32 PayloadLength
;
109 Status
= ScmiCommandGetPayload (&MessageParams
);
110 if (EFI_ERROR (Status
)) {
114 *MessageParams
= DomainId
;
116 Cmd
.ProtocolId
= SCMI_PROTOCOL_ID_PERFORMANCE
;
117 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_DOMAIN_ATTRIBUTES
;
119 PayloadLength
= sizeof (DomainId
);
121 Status
= ScmiCommandExecute (
126 if (EFI_ERROR (Status
)) {
133 sizeof (SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES
)
139 /** Return list of performance domain levels of a given domain.
141 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
142 @param[in] DomainId Identifier for the performance domain.
144 @param[out] NumLevels Total number of levels a domain can support.
146 @param[in,out] LevelArraySize Size of the performance level array.
148 @param[out] LevelArray Array of the performance levels.
150 @retval EFI_SUCCESS Domain levels are returned.
151 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
152 @retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result.
153 It has been updated to the size needed.
154 @retval !(EFI_SUCCESS) Other errors.
158 PerformanceDescribeLevels (
159 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
161 OUT UINT32
*NumLevels
,
162 IN OUT UINT32
*LevelArraySize
,
163 OUT SCMI_PERFORMANCE_LEVEL
*LevelArray
167 UINT32 PayloadLength
;
169 UINT32
* MessageParams
;
173 UINT32 ReturnNumLevels
;
174 UINT32 ReturnRemainNumLevels
;
176 PERF_DESCRIBE_LEVELS
*Levels
;
178 Status
= ScmiCommandGetPayload (&MessageParams
);
179 if (EFI_ERROR (Status
)) {
186 *MessageParams
++ = DomainId
;
188 Cmd
.ProtocolId
= SCMI_PROTOCOL_ID_PERFORMANCE
;
189 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS
;
193 *MessageParams
= LevelIndex
;
195 // Note, PayloadLength is an IN/OUT parameter.
196 PayloadLength
= sizeof (DomainId
) + sizeof (LevelIndex
);
198 Status
= ScmiCommandExecute (
203 if (EFI_ERROR (Status
)) {
207 ReturnNumLevels
= NUM_PERF_LEVELS (Levels
->NumLevels
);
208 ReturnRemainNumLevels
= NUM_REMAIN_PERF_LEVELS (Levels
->NumLevels
);
210 if (RequiredSize
== 0) {
211 *NumLevels
= ReturnNumLevels
+ ReturnRemainNumLevels
;
213 RequiredSize
= (*NumLevels
) * sizeof (SCMI_PERFORMANCE_LEVEL
);
214 if (RequiredSize
> (*LevelArraySize
)) {
215 // Update LevelArraySize with required size.
216 *LevelArraySize
= RequiredSize
;
217 return EFI_BUFFER_TOO_SMALL
;
221 for (LevelNo
= 0; LevelNo
< ReturnNumLevels
; LevelNo
++) {
223 &LevelArray
[LevelIndex
++],
224 &Levels
->PerfLevel
[LevelNo
],
225 sizeof (SCMI_PERFORMANCE_LEVEL
)
229 } while (ReturnRemainNumLevels
!= 0);
231 *LevelArraySize
= RequiredSize
;
236 /** Set performance limits of a domain.
238 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
239 @param[in] DomainId Identifier for the performance domain.
240 @param[in] Limit Performance limit to set.
242 @retval EFI_SUCCESS Performance limits set successfully.
243 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
244 @retval !(EFI_SUCCESS) Other errors.
247 PerformanceLimitsSet (
248 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
250 IN SCMI_PERFORMANCE_LIMITS
*Limits
254 UINT32 PayloadLength
;
256 UINT32
*MessageParams
;
258 Status
= ScmiCommandGetPayload (&MessageParams
);
259 if (EFI_ERROR (Status
)) {
263 *MessageParams
++ = DomainId
;
264 *MessageParams
++ = Limits
->RangeMax
;
265 *MessageParams
= Limits
->RangeMin
;
267 Cmd
.ProtocolId
= SCMI_PROTOCOL_ID_PERFORMANCE
;
268 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET
;
270 PayloadLength
= sizeof (DomainId
) + sizeof (SCMI_PERFORMANCE_LIMITS
);
272 Status
= ScmiCommandExecute (
281 /** Get performance limits of a domain.
283 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
284 @param[in] DomainId Identifier for the performance domain.
286 @param[out] Limit Performance Limits of the domain.
288 @retval EFI_SUCCESS Performance limits are returned.
289 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
290 @retval !(EFI_SUCCESS) Other errors.
293 PerformanceLimitsGet (
294 SCMI_PERFORMANCE_PROTOCOL
*This
,
296 SCMI_PERFORMANCE_LIMITS
*Limits
300 UINT32 PayloadLength
;
302 UINT32
*MessageParams
;
304 SCMI_PERFORMANCE_LIMITS
*ReturnValues
;
306 Status
= ScmiCommandGetPayload (&MessageParams
);
307 if (EFI_ERROR (Status
)) {
311 *MessageParams
= DomainId
;
313 Cmd
.ProtocolId
= SCMI_PROTOCOL_ID_PERFORMANCE
;
314 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET
;
316 PayloadLength
= sizeof (DomainId
);
318 Status
= ScmiCommandExecute (
321 (UINT32
**)&ReturnValues
323 if (EFI_ERROR (Status
)) {
327 Limits
->RangeMax
= ReturnValues
->RangeMax
;
328 Limits
->RangeMin
= ReturnValues
->RangeMin
;
333 /** Set performance level of a domain.
335 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
336 @param[in] DomainId Identifier for the performance domain.
337 @param[in] Level Performance level of the domain.
339 @retval EFI_SUCCESS Performance level set successfully.
340 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
341 @retval !(EFI_SUCCESS) Other errors.
344 PerformanceLevelSet (
345 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
351 UINT32 PayloadLength
;
353 UINT32
*MessageParams
;
355 Status
= ScmiCommandGetPayload (&MessageParams
);
356 if (EFI_ERROR (Status
)) {
360 *MessageParams
++ = DomainId
;
361 *MessageParams
= Level
;
363 Cmd
.ProtocolId
= SCMI_PROTOCOL_ID_PERFORMANCE
;
364 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET
;
366 PayloadLength
= sizeof (DomainId
) + sizeof (Level
);
368 Status
= ScmiCommandExecute (
377 /** Get performance level of a domain.
379 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
380 @param[in] DomainId Identifier for the performance domain.
382 @param[out] Level Performance level of the domain.
384 @retval EFI_SUCCESS Performance level got successfully.
385 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
386 @retval !(EFI_SUCCESS) Other errors.
389 PerformanceLevelGet (
390 IN SCMI_PERFORMANCE_PROTOCOL
*This
,
396 UINT32 PayloadLength
;
398 UINT32
*ReturnValues
;
399 UINT32
*MessageParams
;
401 Status
= ScmiCommandGetPayload (&MessageParams
);
402 if (EFI_ERROR (Status
)) {
406 *MessageParams
= DomainId
;
408 Cmd
.ProtocolId
= SCMI_PROTOCOL_ID_PERFORMANCE
;
409 Cmd
.MessageId
= SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET
;
411 PayloadLength
= sizeof (DomainId
);
413 Status
= ScmiCommandExecute (
418 if (EFI_ERROR (Status
)) {
422 *Level
= *ReturnValues
;
427 // Instance of the SCMI performance management protocol.
428 STATIC CONST SCMI_PERFORMANCE_PROTOCOL PerformanceProtocol
= {
429 PerformanceGetVersion
,
430 PerformanceGetAttributes
,
431 PerformanceDomainAttributes
,
432 PerformanceDescribeLevels
,
433 PerformanceLimitsSet
,
434 PerformanceLimitsGet
,
439 /** Initialize performance management protocol and install on a given Handle.
441 @param[in] Handle Handle to install performance management
444 @retval EFI_SUCCESS Performance protocol installed successfully.
447 ScmiPerformanceProtocolInit (
448 IN EFI_HANDLE
* Handle
451 return gBS
->InstallMultipleProtocolInterfaces (
453 &gArmScmiPerformanceProtocolGuid
,
454 &PerformanceProtocol
,