mirror of https://github.com/acidanthera/audk.git
255 lines
6.8 KiB
C
255 lines
6.8 KiB
C
/** @file
|
|
|
|
Copyright (c) 2017-2021, Arm Limited. All rights reserved.
|
|
|
|
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/ArmMtlLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
|
|
#include "ScmiPrivate.h"
|
|
|
|
// Arbitrary timeout value 20ms.
|
|
#define RESPONSE_TIMEOUT 20000
|
|
|
|
/** Return a pointer to the message payload.
|
|
|
|
@param[out] Payload Holds pointer to the message payload.
|
|
|
|
@retval EFI_SUCCESS Payload holds a valid message payload pointer.
|
|
@retval EFI_TIMEOUT Time out error if MTL channel is busy.
|
|
@retval EFI_UNSUPPORTED If MTL channel is unsupported.
|
|
**/
|
|
EFI_STATUS
|
|
ScmiCommandGetPayload (
|
|
OUT UINT32 **Payload
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
MTL_CHANNEL *Channel;
|
|
|
|
// Get handle to the Channel.
|
|
Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
// Payload will not be populated until channel is free.
|
|
Status = MtlWaitUntilChannelFree (Channel, RESPONSE_TIMEOUT);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
// Get the address of the payload.
|
|
*Payload = MtlGetChannelPayload (Channel);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/** Execute a SCMI command and receive a response.
|
|
|
|
This function uses a MTL channel to transfer message to SCP
|
|
and waits for a response.
|
|
|
|
@param[in] Command Pointer to the SCMI command (Protocol ID
|
|
and Message ID)
|
|
|
|
@param[in,out] PayloadLength SCMI command message length.
|
|
|
|
@param[out] OPTIONAL ReturnValues Pointer to SCMI response.
|
|
|
|
@retval OUT EFI_SUCCESS Command sent and message received successfully.
|
|
@retval OUT EFI_UNSUPPORTED Channel not supported.
|
|
@retval OUT EFI_TIMEOUT Timeout on the channel.
|
|
@retval OUT EFI_DEVICE_ERROR Channel not ready.
|
|
@retval OUT EFI_DEVICE_ERROR Message Header corrupted.
|
|
@retval OUT EFI_DEVICE_ERROR SCMI error.
|
|
**/
|
|
EFI_STATUS
|
|
ScmiCommandExecute (
|
|
IN SCMI_COMMAND *Command,
|
|
IN OUT UINT32 *PayloadLength,
|
|
OUT UINT32 **ReturnValues OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SCMI_MESSAGE_RESPONSE *Response;
|
|
UINT32 MessageHeader;
|
|
UINT32 ResponseHeader;
|
|
MTL_CHANNEL *Channel;
|
|
|
|
ASSERT (PayloadLength != NULL);
|
|
|
|
Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
// Fill in message header.
|
|
MessageHeader = SCMI_MESSAGE_HEADER (
|
|
Command->MessageId,
|
|
ScmiMessageTypeCommand,
|
|
Command->ProtocolId
|
|
);
|
|
|
|
// Send payload using MTL channel.
|
|
Status = MtlSendMessage (
|
|
Channel,
|
|
MessageHeader,
|
|
*PayloadLength
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
// Wait for the response on the channel.
|
|
Status = MtlReceiveMessage (Channel, &ResponseHeader, PayloadLength);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
// SCMI must return MessageHeader unmodified.
|
|
if (MessageHeader != ResponseHeader) {
|
|
ASSERT (FALSE);
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
Response = (SCMI_MESSAGE_RESPONSE *)MtlGetChannelPayload (Channel);
|
|
|
|
if (Response->Status != ScmiSuccess) {
|
|
DEBUG ((
|
|
DEBUG_ERROR,
|
|
"SCMI error: ProtocolId = 0x%x, MessageId = 0x%x, error = %d\n",
|
|
Command->ProtocolId,
|
|
Command->MessageId,
|
|
Response->Status
|
|
));
|
|
|
|
ASSERT (FALSE);
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
if (ReturnValues != NULL) {
|
|
*ReturnValues = Response->ReturnValues;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/** Internal common function useful for common protocol discovery messages.
|
|
|
|
@param[in] ProtocolId Protocol Id of the protocol.
|
|
@param[in] MessageId Message Id of the message.
|
|
|
|
@param[out] ReturnValues SCMI response return values.
|
|
|
|
@retval EFI_SUCCESS Success with valid return values.
|
|
@retval EFI_DEVICE_ERROR SCMI error.
|
|
@retval !(EFI_SUCCESS) Other errors.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
ScmiProtocolDiscoveryCommon (
|
|
IN SCMI_PROTOCOL_ID ProtocolId,
|
|
IN SCMI_MESSAGE_ID MessageId,
|
|
OUT UINT32 **ReturnValues
|
|
)
|
|
{
|
|
SCMI_COMMAND Command;
|
|
UINT32 PayloadLength;
|
|
|
|
PayloadLength = 0;
|
|
Command.ProtocolId = ProtocolId;
|
|
Command.MessageId = MessageId;
|
|
|
|
return ScmiCommandExecute (
|
|
&Command,
|
|
&PayloadLength,
|
|
ReturnValues
|
|
);
|
|
}
|
|
|
|
/** Return protocol version from SCP for a given protocol ID.
|
|
|
|
@param[in] Protocol ID Protocol ID.
|
|
@param[out] Version Pointer to version of the protocol.
|
|
|
|
@retval EFI_SUCCESS Version holds a valid version received
|
|
from the SCP.
|
|
@retval EFI_DEVICE_ERROR SCMI error.
|
|
@retval !(EFI_SUCCESS) Other errors.
|
|
**/
|
|
EFI_STATUS
|
|
ScmiGetProtocolVersion (
|
|
IN SCMI_PROTOCOL_ID ProtocolId,
|
|
OUT UINT32 *Version
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 *ProtocolVersion;
|
|
|
|
Status = ScmiProtocolDiscoveryCommon (
|
|
ProtocolId,
|
|
ScmiMessageIdProtocolVersion,
|
|
(UINT32 **)&ProtocolVersion
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
*Version = *ProtocolVersion;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/** Return protocol attributes from SCP for a given protocol ID.
|
|
|
|
@param[in] Protocol ID Protocol ID.
|
|
@param[out] ReturnValues Pointer to attributes of the protocol.
|
|
|
|
@retval EFI_SUCCESS ReturnValues points to protocol attributes.
|
|
@retval EFI_DEVICE_ERROR SCMI error.
|
|
@retval !(EFI_SUCCESS) Other errors.
|
|
**/
|
|
EFI_STATUS
|
|
ScmiGetProtocolAttributes (
|
|
IN SCMI_PROTOCOL_ID ProtocolId,
|
|
OUT UINT32 **ReturnValues
|
|
)
|
|
{
|
|
return ScmiProtocolDiscoveryCommon (
|
|
ProtocolId,
|
|
ScmiMessageIdProtocolAttributes,
|
|
ReturnValues
|
|
);
|
|
}
|
|
|
|
/** Return protocol message attributes from SCP for a given protocol ID.
|
|
|
|
@param[in] Protocol ID Protocol ID.
|
|
@param[out] Attributes Pointer to attributes of the protocol.
|
|
|
|
@retval EFI_SUCCESS ReturnValues points to protocol message attributes.
|
|
@retval EFI_DEVICE_ERROR SCMI error.
|
|
@retval !(EFI_SUCCESS) Other errors.
|
|
**/
|
|
EFI_STATUS
|
|
ScmiGetProtocolMessageAttributes (
|
|
IN SCMI_PROTOCOL_ID ProtocolId,
|
|
OUT UINT32 **ReturnValues
|
|
)
|
|
{
|
|
return ScmiProtocolDiscoveryCommon (
|
|
ProtocolId,
|
|
ScmiMessageIdProtocolMessageAttributes,
|
|
ReturnValues
|
|
);
|
|
}
|