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