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/ArmMtlLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
23 #include "ScmiPrivate.h"
25 // SCMI Specification 1.0
26 #define MAX_PROTOCOLS 6
28 #define PROTOCOL_MASK 0xF
30 // Arbitrary timeout value 20ms.
31 #define RESPONSE_TIMEOUT 20000
33 /** Return a pointer to the message payload.
35 @param[out] Payload Holds pointer to the message payload.
37 @retval EFI_SUCCESS Payload holds a valid message payload pointer.
38 @retval EFI_TIMEOUT Time out error if MTL channel is busy.
39 @retval EFI_UNSUPPORTED If MTL channel is unsupported.
42 ScmiCommandGetPayload (
49 // Get handle to the Channel.
50 Status
= MtlGetChannel (MTL_CHANNEL_TYPE_LOW
, &Channel
);
51 if (EFI_ERROR (Status
)) {
55 // Payload will not be populated until channel is free.
56 Status
= MtlWaitUntilChannelFree (Channel
, RESPONSE_TIMEOUT
);
57 if (EFI_ERROR (Status
)) {
61 // Get the address of the payload.
62 *Payload
= MtlGetChannelPayload (Channel
);
67 /** Execute a SCMI command and receive a response.
69 This function uses a MTL channel to transfer message to SCP
70 and waits for a response.
72 @param[in] Command Pointer to the SCMI command (Protocol ID
75 @param[in,out] PayloadLength SCMI command message length.
77 @param[out] OPTIONAL ReturnValues Pointer to SCMI response.
79 @retval OUT EFI_SUCCESS Command sent and message received successfully.
80 @retval OUT EFI_UNSUPPORTED Channel not supported.
81 @retval OUT EFI_TIMEOUT Timeout on the channel.
82 @retval OUT EFI_DEVICE_ERROR Channel not ready.
83 @retval OUT EFI_DEVICE_ERROR Message Header corrupted.
84 @retval OUT EFI_DEVICE_ERROR SCMI error.
88 IN SCMI_COMMAND
*Command
,
89 IN OUT UINT32
*PayloadLength
,
90 OUT UINT32
**ReturnValues OPTIONAL
94 SCMI_MESSAGE_RESPONSE
*Response
;
96 UINT32 ResponseHeader
;
99 ASSERT (PayloadLength
!= NULL
);
101 Status
= MtlGetChannel (MTL_CHANNEL_TYPE_LOW
, &Channel
);
102 if (EFI_ERROR (Status
)) {
106 // Fill in message header.
107 MessageHeader
= SCMI_MESSAGE_HEADER (
109 SCMI_MESSAGE_TYPE_COMMAND
,
113 // Send payload using MTL channel.
114 Status
= MtlSendMessage (
119 if (EFI_ERROR (Status
)) {
123 // Wait for the response on the channel.
124 Status
= MtlReceiveMessage (Channel
, &ResponseHeader
, PayloadLength
);
125 if (EFI_ERROR (Status
)) {
129 // SCMI must return MessageHeader unmodified.
130 if (MessageHeader
!= ResponseHeader
) {
132 return EFI_DEVICE_ERROR
;
135 Response
= (SCMI_MESSAGE_RESPONSE
*)MtlGetChannelPayload (Channel
);
137 if (Response
->Status
!= SCMI_SUCCESS
) {
138 DEBUG ((DEBUG_ERROR
, "SCMI error: ProtocolId = 0x%x, MessageId = 0x%x, error = %d\n",
145 return EFI_DEVICE_ERROR
;
148 if (ReturnValues
!= NULL
) {
149 *ReturnValues
= Response
->ReturnValues
;
155 /** Internal common function useful for common protocol discovery messages.
157 @param[in] ProtocolId Protocol Id of the the protocol.
158 @param[in] MesaageId Message Id of the message.
160 @param[out] ReturnValues SCMI response return values.
162 @retval EFI_SUCCESS Success with valid return values.
163 @retval EFI_DEVICE_ERROR SCMI error.
164 @retval !(EFI_SUCCESS) Other errors.
168 ScmiProtocolDiscoveryCommon (
169 IN SCMI_PROTOCOL_ID ProtocolId
,
170 IN SCMI_MESSAGE_ID MessageId
,
171 OUT UINT32
**ReturnValues
174 SCMI_COMMAND Command
;
175 UINT32 PayloadLength
= 0;
177 Command
.ProtocolId
= ProtocolId
;
178 Command
.MessageId
= MessageId
;
180 return ScmiCommandExecute (
187 /** Return protocol version from SCP for a given protocol ID.
189 @param[in] Protocol ID Protocol ID.
190 @param[out] Version Pointer to version of the protocol.
192 @retval EFI_SUCCESS Version holds a valid version received
194 @retval EFI_DEVICE_ERROR SCMI error.
195 @retval !(EFI_SUCCESS) Other errors.
198 ScmiGetProtocolVersion (
199 IN SCMI_PROTOCOL_ID ProtocolId
,
204 UINT32
*ProtocolVersion
;
206 Status
= ScmiProtocolDiscoveryCommon (
208 SCMI_MESSAGE_ID_PROTOCOL_VERSION
,
209 (UINT32
**)&ProtocolVersion
211 if (EFI_ERROR (Status
)) {
215 *Version
= *ProtocolVersion
;
220 /** Return protocol attributes from SCP for a given protocol ID.
222 @param[in] Protocol ID Protocol ID.
223 @param[out] ReturnValues Pointer to attributes of the protocol.
225 @retval EFI_SUCCESS ReturnValues points to protocol attributes.
226 @retval EFI_DEVICE_ERROR SCMI error.
227 @retval !(EFI_SUCCESS) Other errors.
230 ScmiGetProtocolAttributes (
231 IN SCMI_PROTOCOL_ID ProtocolId
,
232 OUT UINT32
**ReturnValues
235 return ScmiProtocolDiscoveryCommon (
237 SCMI_MESSAGE_ID_PROTOCOL_ATTRIBUTES
,
242 /** Return protocol message attributes from SCP for a given protocol ID.
244 @param[in] Protocol ID Protocol ID.
245 @param[out] Attributes Pointer to attributes of the protocol.
247 @retval EFI_SUCCESS ReturnValues points to protocol message attributes.
248 @retval EFI_DEVICE_ERROR SCMI error.
249 @retval !(EFI_SUCCESS) Other errors.
252 ScmiGetProtocolMessageAttributes (
253 IN SCMI_PROTOCOL_ID ProtocolId
,
254 OUT UINT32
**ReturnValues
257 return ScmiProtocolDiscoveryCommon (
259 SCMI_MESSAGE_ID_PROTOCOL_MESSAGE_ATTRIBUTES
,