mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-01 12:53:27 +01:00
450 lines
12 KiB
C
450 lines
12 KiB
C
|
/** @file
|
||
|
|
||
|
Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR>
|
||
|
|
||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
|
||
|
System Control and Management Interface V1.0
|
||
|
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||
|
DEN0056A_System_Control_and_Management_Interface.pdf
|
||
|
**/
|
||
|
|
||
|
#include <Library/BaseMemoryLib.h>
|
||
|
#include <Library/UefiBootServicesTableLib.h>
|
||
|
#include <Protocol/ArmScmiPerformanceProtocol.h>
|
||
|
|
||
|
#include "ArmScmiPerformanceProtocolPrivate.h"
|
||
|
#include "ScmiPrivate.h"
|
||
|
|
||
|
/** Return version of the performance management protocol supported by SCP.
|
||
|
firmware.
|
||
|
|
||
|
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||
|
|
||
|
@param[out] Version Version of the supported SCMI performance management
|
||
|
protocol.
|
||
|
|
||
|
@retval EFI_SUCCESS The version is returned.
|
||
|
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||
|
@retval !(EFI_SUCCESS) Other errors.
|
||
|
**/
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
PerformanceGetVersion (
|
||
|
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||
|
OUT UINT32 *Version
|
||
|
)
|
||
|
{
|
||
|
return ScmiGetProtocolVersion (ScmiProtocolIdPerformance, Version);
|
||
|
}
|
||
|
|
||
|
/** Return protocol attributes of the performance management protocol.
|
||
|
|
||
|
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||
|
|
||
|
@param[out] Attributes Protocol attributes.
|
||
|
|
||
|
@retval EFI_SUCCESS Protocol attributes are returned.
|
||
|
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||
|
@retval !(EFI_SUCCESS) Other errors.
|
||
|
**/
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
PerformanceGetAttributes (
|
||
|
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||
|
OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES *Attributes
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINT32 *ReturnValues;
|
||
|
|
||
|
Status = ScmiGetProtocolAttributes (
|
||
|
ScmiProtocolIdPerformance,
|
||
|
&ReturnValues
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
CopyMem (
|
||
|
Attributes,
|
||
|
ReturnValues,
|
||
|
sizeof (SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES)
|
||
|
);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/** Return performance domain attributes.
|
||
|
|
||
|
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||
|
@param[in] DomainId Identifier for the performance domain.
|
||
|
|
||
|
@param[out] Attributes Performance domain attributes.
|
||
|
|
||
|
@retval EFI_SUCCESS Domain attributes are returned.
|
||
|
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||
|
@retval !(EFI_SUCCESS) Other errors.
|
||
|
**/
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
PerformanceDomainAttributes (
|
||
|
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||
|
IN UINT32 DomainId,
|
||
|
OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES *DomainAttributes
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINT32 *MessageParams;
|
||
|
UINT32 *ReturnValues;
|
||
|
UINT32 PayloadLength;
|
||
|
SCMI_COMMAND Cmd;
|
||
|
|
||
|
Status = ScmiCommandGetPayload (&MessageParams);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
*MessageParams = DomainId;
|
||
|
|
||
|
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||
|
Cmd.MessageId = ScmiMessageIdPerformanceDomainAttributes;
|
||
|
|
||
|
PayloadLength = sizeof (DomainId);
|
||
|
|
||
|
Status = ScmiCommandExecute (
|
||
|
&Cmd,
|
||
|
&PayloadLength,
|
||
|
&ReturnValues
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
CopyMem (
|
||
|
DomainAttributes,
|
||
|
ReturnValues,
|
||
|
sizeof (SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES)
|
||
|
);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/** Return list of performance domain levels of a given domain.
|
||
|
|
||
|
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||
|
@param[in] DomainId Identifier for the performance domain.
|
||
|
|
||
|
@param[out] NumLevels Total number of levels a domain can support.
|
||
|
|
||
|
@param[in,out] LevelArraySize Size of the performance level array.
|
||
|
|
||
|
@param[out] LevelArray Array of the performance levels.
|
||
|
|
||
|
@retval EFI_SUCCESS Domain levels are returned.
|
||
|
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||
|
@retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result.
|
||
|
It has been updated to the size needed.
|
||
|
@retval !(EFI_SUCCESS) Other errors.
|
||
|
**/
|
||
|
STATIC
|
||
|
EFI_STATUS
|
||
|
PerformanceDescribeLevels (
|
||
|
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||
|
IN UINT32 DomainId,
|
||
|
OUT UINT32 *NumLevels,
|
||
|
IN OUT UINT32 *LevelArraySize,
|
||
|
OUT SCMI_PERFORMANCE_LEVEL *LevelArray
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINT32 PayloadLength;
|
||
|
SCMI_COMMAND Cmd;
|
||
|
UINT32 *MessageParams;
|
||
|
UINT32 LevelIndex;
|
||
|
UINT32 RequiredSize;
|
||
|
UINT32 LevelNo;
|
||
|
UINT32 ReturnNumLevels;
|
||
|
UINT32 ReturnRemainNumLevels;
|
||
|
|
||
|
PERF_DESCRIBE_LEVELS *Levels;
|
||
|
|
||
|
Status = ScmiCommandGetPayload (&MessageParams);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
LevelIndex = 0;
|
||
|
RequiredSize = 0;
|
||
|
|
||
|
*MessageParams++ = DomainId;
|
||
|
|
||
|
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||
|
Cmd.MessageId = ScmiMessageIdPerformanceDescribeLevels;
|
||
|
|
||
|
do {
|
||
|
*MessageParams = LevelIndex;
|
||
|
|
||
|
// Note, PayloadLength is an IN/OUT parameter.
|
||
|
PayloadLength = sizeof (DomainId) + sizeof (LevelIndex);
|
||
|
|
||
|
Status = ScmiCommandExecute (
|
||
|
&Cmd,
|
||
|
&PayloadLength,
|
||
|
(UINT32 **)&Levels
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
ReturnNumLevels = NUM_PERF_LEVELS (Levels->NumLevels);
|
||
|
ReturnRemainNumLevels = NUM_REMAIN_PERF_LEVELS (Levels->NumLevels);
|
||
|
|
||
|
if (RequiredSize == 0) {
|
||
|
*NumLevels = ReturnNumLevels + ReturnRemainNumLevels;
|
||
|
|
||
|
RequiredSize = (*NumLevels) * sizeof (SCMI_PERFORMANCE_LEVEL);
|
||
|
if (RequiredSize > (*LevelArraySize)) {
|
||
|
// Update LevelArraySize with required size.
|
||
|
*LevelArraySize = RequiredSize;
|
||
|
return EFI_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (LevelNo = 0; LevelNo < ReturnNumLevels; LevelNo++) {
|
||
|
CopyMem (
|
||
|
&LevelArray[LevelIndex++],
|
||
|
&Levels->PerfLevel[LevelNo],
|
||
|
sizeof (SCMI_PERFORMANCE_LEVEL)
|
||
|
);
|
||
|
}
|
||
|
} while (ReturnRemainNumLevels != 0);
|
||
|
|
||
|
*LevelArraySize = RequiredSize;
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/** Set performance limits of a domain.
|
||
|
|
||
|
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||
|
@param[in] DomainId Identifier for the performance domain.
|
||
|
@param[in] Limit Performance limit to set.
|
||
|
|
||
|
@retval EFI_SUCCESS Performance limits set successfully.
|
||
|
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||
|
@retval !(EFI_SUCCESS) Other errors.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
PerformanceLimitsSet (
|
||
|
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||
|
IN UINT32 DomainId,
|
||
|
IN SCMI_PERFORMANCE_LIMITS *Limits
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINT32 PayloadLength;
|
||
|
SCMI_COMMAND Cmd;
|
||
|
UINT32 *MessageParams;
|
||
|
|
||
|
Status = ScmiCommandGetPayload (&MessageParams);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
*MessageParams++ = DomainId;
|
||
|
*MessageParams++ = Limits->RangeMax;
|
||
|
*MessageParams = Limits->RangeMin;
|
||
|
|
||
|
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||
|
Cmd.MessageId = ScmiMessageIdPerformanceLimitsSet;
|
||
|
|
||
|
PayloadLength = sizeof (DomainId) + sizeof (SCMI_PERFORMANCE_LIMITS);
|
||
|
|
||
|
Status = ScmiCommandExecute (
|
||
|
&Cmd,
|
||
|
&PayloadLength,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/** Get performance limits of a domain.
|
||
|
|
||
|
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||
|
@param[in] DomainId Identifier for the performance domain.
|
||
|
|
||
|
@param[out] Limit Performance Limits of the domain.
|
||
|
|
||
|
@retval EFI_SUCCESS Performance limits are returned.
|
||
|
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||
|
@retval !(EFI_SUCCESS) Other errors.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
PerformanceLimitsGet (
|
||
|
SCMI_PERFORMANCE_PROTOCOL *This,
|
||
|
UINT32 DomainId,
|
||
|
SCMI_PERFORMANCE_LIMITS *Limits
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINT32 PayloadLength;
|
||
|
SCMI_COMMAND Cmd;
|
||
|
UINT32 *MessageParams;
|
||
|
|
||
|
SCMI_PERFORMANCE_LIMITS *ReturnValues;
|
||
|
|
||
|
Status = ScmiCommandGetPayload (&MessageParams);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
*MessageParams = DomainId;
|
||
|
|
||
|
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||
|
Cmd.MessageId = ScmiMessageIdPerformanceLimitsGet;
|
||
|
|
||
|
PayloadLength = sizeof (DomainId);
|
||
|
|
||
|
Status = ScmiCommandExecute (
|
||
|
&Cmd,
|
||
|
&PayloadLength,
|
||
|
(UINT32 **)&ReturnValues
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
Limits->RangeMax = ReturnValues->RangeMax;
|
||
|
Limits->RangeMin = ReturnValues->RangeMin;
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/** Set performance level of a domain.
|
||
|
|
||
|
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||
|
@param[in] DomainId Identifier for the performance domain.
|
||
|
@param[in] Level Performance level of the domain.
|
||
|
|
||
|
@retval EFI_SUCCESS Performance level set successfully.
|
||
|
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||
|
@retval !(EFI_SUCCESS) Other errors.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
PerformanceLevelSet (
|
||
|
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||
|
IN UINT32 DomainId,
|
||
|
IN UINT32 Level
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINT32 PayloadLength;
|
||
|
SCMI_COMMAND Cmd;
|
||
|
UINT32 *MessageParams;
|
||
|
|
||
|
Status = ScmiCommandGetPayload (&MessageParams);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
*MessageParams++ = DomainId;
|
||
|
*MessageParams = Level;
|
||
|
|
||
|
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||
|
Cmd.MessageId = ScmiMessageIdPerformanceLevelSet;
|
||
|
|
||
|
PayloadLength = sizeof (DomainId) + sizeof (Level);
|
||
|
|
||
|
Status = ScmiCommandExecute (
|
||
|
&Cmd,
|
||
|
&PayloadLength,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/** Get performance level of a domain.
|
||
|
|
||
|
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||
|
@param[in] DomainId Identifier for the performance domain.
|
||
|
|
||
|
@param[out] Level Performance level of the domain.
|
||
|
|
||
|
@retval EFI_SUCCESS Performance level got successfully.
|
||
|
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||
|
@retval !(EFI_SUCCESS) Other errors.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
PerformanceLevelGet (
|
||
|
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||
|
IN UINT32 DomainId,
|
||
|
OUT UINT32 *Level
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINT32 PayloadLength;
|
||
|
SCMI_COMMAND Cmd;
|
||
|
UINT32 *ReturnValues;
|
||
|
UINT32 *MessageParams;
|
||
|
|
||
|
Status = ScmiCommandGetPayload (&MessageParams);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
*MessageParams = DomainId;
|
||
|
|
||
|
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||
|
Cmd.MessageId = ScmiMessageIdPerformanceLevelGet;
|
||
|
|
||
|
PayloadLength = sizeof (DomainId);
|
||
|
|
||
|
Status = ScmiCommandExecute (
|
||
|
&Cmd,
|
||
|
&PayloadLength,
|
||
|
&ReturnValues
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
*Level = *ReturnValues;
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
// Instance of the SCMI performance management protocol.
|
||
|
STATIC CONST SCMI_PERFORMANCE_PROTOCOL PerformanceProtocol = {
|
||
|
PerformanceGetVersion,
|
||
|
PerformanceGetAttributes,
|
||
|
PerformanceDomainAttributes,
|
||
|
PerformanceDescribeLevels,
|
||
|
PerformanceLimitsSet,
|
||
|
PerformanceLimitsGet,
|
||
|
PerformanceLevelSet,
|
||
|
PerformanceLevelGet
|
||
|
};
|
||
|
|
||
|
/** Initialize performance management protocol and install on a given Handle.
|
||
|
|
||
|
@param[in] Handle Handle to install performance management
|
||
|
protocol.
|
||
|
|
||
|
@retval EFI_SUCCESS Performance protocol installed successfully.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ScmiPerformanceProtocolInit (
|
||
|
IN EFI_HANDLE *Handle
|
||
|
)
|
||
|
{
|
||
|
return gBS->InstallMultipleProtocolInterfaces (
|
||
|
Handle,
|
||
|
&gArmScmiPerformanceProtocolGuid,
|
||
|
&PerformanceProtocol,
|
||
|
NULL
|
||
|
);
|
||
|
}
|