]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Drivers/ArmScmiDxe/Scmi.c
ArmPkg: Introduce SCMI protocol
[mirror_edk2.git] / ArmPkg / Drivers / ArmScmiDxe / Scmi.c
1 /** @file
2
3 Copyright (c) 2017-2018, Arm Limited. All rights reserved.
4
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
9
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.
12
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
16 **/
17
18 #include <Library/ArmMtlLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22
23 #include "ScmiPrivate.h"
24
25 // SCMI Specification 1.0
26 #define MAX_PROTOCOLS 6
27
28 #define PROTOCOL_MASK 0xF
29
30 // Arbitrary timeout value 20ms.
31 #define RESPONSE_TIMEOUT 20000
32
33 /** Return a pointer to the message payload.
34
35 @param[out] Payload Holds pointer to the message payload.
36
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.
40 **/
41 EFI_STATUS
42 ScmiCommandGetPayload (
43 OUT UINT32** Payload
44 )
45 {
46 EFI_STATUS Status;
47 MTL_CHANNEL *Channel;
48
49 // Get handle to the Channel.
50 Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel);
51 if (EFI_ERROR (Status)) {
52 return Status;
53 }
54
55 // Payload will not be populated until channel is free.
56 Status = MtlWaitUntilChannelFree (Channel, RESPONSE_TIMEOUT);
57 if (EFI_ERROR (Status)) {
58 return Status;
59 }
60
61 // Get the address of the payload.
62 *Payload = MtlGetChannelPayload (Channel);
63
64 return EFI_SUCCESS;
65 }
66
67 /** Execute a SCMI command and receive a response.
68
69 This function uses a MTL channel to transfer message to SCP
70 and waits for a response.
71
72 @param[in] Command Pointer to the SCMI command (Protocol ID
73 and Message ID)
74
75 @param[in,out] PayloadLength SCMI command message length.
76
77 @param[out] OPTIONAL ReturnValues Pointer to SCMI response.
78
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.
85 **/
86 EFI_STATUS
87 ScmiCommandExecute (
88 IN SCMI_COMMAND *Command,
89 IN OUT UINT32 *PayloadLength,
90 OUT UINT32 **ReturnValues OPTIONAL
91 )
92 {
93 EFI_STATUS Status;
94 SCMI_MESSAGE_RESPONSE *Response;
95 UINT32 MessageHeader;
96 UINT32 ResponseHeader;
97 MTL_CHANNEL *Channel;
98
99 ASSERT (PayloadLength != NULL);
100
101 Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel);
102 if (EFI_ERROR (Status)) {
103 return Status;
104 }
105
106 // Fill in message header.
107 MessageHeader = SCMI_MESSAGE_HEADER (
108 Command->MessageId,
109 SCMI_MESSAGE_TYPE_COMMAND,
110 Command->ProtocolId
111 );
112
113 // Send payload using MTL channel.
114 Status = MtlSendMessage (
115 Channel,
116 MessageHeader,
117 *PayloadLength
118 );
119 if (EFI_ERROR (Status)) {
120 return Status;
121 }
122
123 // Wait for the response on the channel.
124 Status = MtlReceiveMessage (Channel, &ResponseHeader, PayloadLength);
125 if (EFI_ERROR (Status)) {
126 return Status;
127 }
128
129 // SCMI must return MessageHeader unmodified.
130 if (MessageHeader != ResponseHeader) {
131 ASSERT (FALSE);
132 return EFI_DEVICE_ERROR;
133 }
134
135 Response = (SCMI_MESSAGE_RESPONSE*)MtlGetChannelPayload (Channel);
136
137 if (Response->Status != SCMI_SUCCESS) {
138 DEBUG ((DEBUG_ERROR, "SCMI error: ProtocolId = 0x%x, MessageId = 0x%x, error = %d\n",
139 Command->ProtocolId,
140 Command->MessageId,
141 Response->Status
142 ));
143
144 ASSERT (FALSE);
145 return EFI_DEVICE_ERROR;
146 }
147
148 if (ReturnValues != NULL) {
149 *ReturnValues = Response->ReturnValues;
150 }
151
152 return EFI_SUCCESS;
153 }
154
155 /** Internal common function useful for common protocol discovery messages.
156
157 @param[in] ProtocolId Protocol Id of the the protocol.
158 @param[in] MesaageId Message Id of the message.
159
160 @param[out] ReturnValues SCMI response return values.
161
162 @retval EFI_SUCCESS Success with valid return values.
163 @retval EFI_DEVICE_ERROR SCMI error.
164 @retval !(EFI_SUCCESS) Other errors.
165 **/
166 STATIC
167 EFI_STATUS
168 ScmiProtocolDiscoveryCommon (
169 IN SCMI_PROTOCOL_ID ProtocolId,
170 IN SCMI_MESSAGE_ID MessageId,
171 OUT UINT32 **ReturnValues
172 )
173 {
174 SCMI_COMMAND Command;
175 UINT32 PayloadLength = 0;
176
177 Command.ProtocolId = ProtocolId;
178 Command.MessageId = MessageId;
179
180 return ScmiCommandExecute (
181 &Command,
182 &PayloadLength,
183 ReturnValues
184 );
185 }
186
187 /** Return protocol version from SCP for a given protocol ID.
188
189 @param[in] Protocol ID Protocol ID.
190 @param[out] Version Pointer to version of the protocol.
191
192 @retval EFI_SUCCESS Version holds a valid version received
193 from the SCP.
194 @retval EFI_DEVICE_ERROR SCMI error.
195 @retval !(EFI_SUCCESS) Other errors.
196 **/
197 EFI_STATUS
198 ScmiGetProtocolVersion (
199 IN SCMI_PROTOCOL_ID ProtocolId,
200 OUT UINT32 *Version
201 )
202 {
203 EFI_STATUS Status;
204 UINT32 *ProtocolVersion;
205
206 Status = ScmiProtocolDiscoveryCommon (
207 ProtocolId,
208 SCMI_MESSAGE_ID_PROTOCOL_VERSION,
209 (UINT32**)&ProtocolVersion
210 );
211 if (EFI_ERROR (Status)) {
212 return Status;
213 }
214
215 *Version = *ProtocolVersion;
216
217 return EFI_SUCCESS;
218 }
219
220 /** Return protocol attributes from SCP for a given protocol ID.
221
222 @param[in] Protocol ID Protocol ID.
223 @param[out] ReturnValues Pointer to attributes of the protocol.
224
225 @retval EFI_SUCCESS ReturnValues points to protocol attributes.
226 @retval EFI_DEVICE_ERROR SCMI error.
227 @retval !(EFI_SUCCESS) Other errors.
228 **/
229 EFI_STATUS
230 ScmiGetProtocolAttributes (
231 IN SCMI_PROTOCOL_ID ProtocolId,
232 OUT UINT32 **ReturnValues
233 )
234 {
235 return ScmiProtocolDiscoveryCommon (
236 ProtocolId,
237 SCMI_MESSAGE_ID_PROTOCOL_ATTRIBUTES,
238 ReturnValues
239 );
240 }
241
242 /** Return protocol message attributes from SCP for a given protocol ID.
243
244 @param[in] Protocol ID Protocol ID.
245 @param[out] Attributes Pointer to attributes of the protocol.
246
247 @retval EFI_SUCCESS ReturnValues points to protocol message attributes.
248 @retval EFI_DEVICE_ERROR SCMI error.
249 @retval !(EFI_SUCCESS) Other errors.
250 **/
251 EFI_STATUS
252 ScmiGetProtocolMessageAttributes (
253 IN SCMI_PROTOCOL_ID ProtocolId,
254 OUT UINT32 **ReturnValues
255 )
256 {
257 return ScmiProtocolDiscoveryCommon (
258 ProtocolId,
259 SCMI_MESSAGE_ID_PROTOCOL_MESSAGE_ATTRIBUTES,
260 ReturnValues
261 );
262 }