]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Drivers/ArmScmiDxe/Scmi.c
fcf4ed496f265dcf59aaaa660467f0ee9f3e9a84
[mirror_edk2.git] / ArmPkg / Drivers / ArmScmiDxe / Scmi.c
1 /** @file
2
3 Copyright (c) 2017-2021, 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 ScmiMessageTypeCommand,
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 != ScmiSuccess) {
127 DEBUG ((
128 DEBUG_ERROR,
129 "SCMI error: ProtocolId = 0x%x, MessageId = 0x%x, error = %d\n",
130 Command->ProtocolId,
131 Command->MessageId,
132 Response->Status
133 ));
134
135 ASSERT (FALSE);
136 return EFI_DEVICE_ERROR;
137 }
138
139 if (ReturnValues != NULL) {
140 *ReturnValues = Response->ReturnValues;
141 }
142
143 return EFI_SUCCESS;
144 }
145
146 /** Internal common function useful for common protocol discovery messages.
147
148 @param[in] ProtocolId Protocol Id of the protocol.
149 @param[in] MessageId Message Id of the message.
150
151 @param[out] ReturnValues SCMI response return values.
152
153 @retval EFI_SUCCESS Success with valid return values.
154 @retval EFI_DEVICE_ERROR SCMI error.
155 @retval !(EFI_SUCCESS) Other errors.
156 **/
157 STATIC
158 EFI_STATUS
159 ScmiProtocolDiscoveryCommon (
160 IN SCMI_PROTOCOL_ID ProtocolId,
161 IN SCMI_MESSAGE_ID MessageId,
162 OUT UINT32 **ReturnValues
163 )
164 {
165 SCMI_COMMAND Command;
166 UINT32 PayloadLength;
167
168 PayloadLength = 0;
169 Command.ProtocolId = ProtocolId;
170 Command.MessageId = MessageId;
171
172 return ScmiCommandExecute (
173 &Command,
174 &PayloadLength,
175 ReturnValues
176 );
177 }
178
179 /** Return protocol version from SCP for a given protocol ID.
180
181 @param[in] Protocol ID Protocol ID.
182 @param[out] Version Pointer to version of the protocol.
183
184 @retval EFI_SUCCESS Version holds a valid version received
185 from the SCP.
186 @retval EFI_DEVICE_ERROR SCMI error.
187 @retval !(EFI_SUCCESS) Other errors.
188 **/
189 EFI_STATUS
190 ScmiGetProtocolVersion (
191 IN SCMI_PROTOCOL_ID ProtocolId,
192 OUT UINT32 *Version
193 )
194 {
195 EFI_STATUS Status;
196 UINT32 *ProtocolVersion;
197
198 Status = ScmiProtocolDiscoveryCommon (
199 ProtocolId,
200 ScmiMessageIdProtocolVersion,
201 (UINT32 **)&ProtocolVersion
202 );
203 if (EFI_ERROR (Status)) {
204 return Status;
205 }
206
207 *Version = *ProtocolVersion;
208
209 return EFI_SUCCESS;
210 }
211
212 /** Return protocol attributes from SCP for a given protocol ID.
213
214 @param[in] Protocol ID Protocol ID.
215 @param[out] ReturnValues Pointer to attributes of the protocol.
216
217 @retval EFI_SUCCESS ReturnValues points to protocol attributes.
218 @retval EFI_DEVICE_ERROR SCMI error.
219 @retval !(EFI_SUCCESS) Other errors.
220 **/
221 EFI_STATUS
222 ScmiGetProtocolAttributes (
223 IN SCMI_PROTOCOL_ID ProtocolId,
224 OUT UINT32 **ReturnValues
225 )
226 {
227 return ScmiProtocolDiscoveryCommon (
228 ProtocolId,
229 ScmiMessageIdProtocolAttributes,
230 ReturnValues
231 );
232 }
233
234 /** Return protocol message attributes from SCP for a given protocol ID.
235
236 @param[in] Protocol ID Protocol ID.
237 @param[out] Attributes Pointer to attributes of the protocol.
238
239 @retval EFI_SUCCESS ReturnValues points to protocol message attributes.
240 @retval EFI_DEVICE_ERROR SCMI error.
241 @retval !(EFI_SUCCESS) Other errors.
242 **/
243 EFI_STATUS
244 ScmiGetProtocolMessageAttributes (
245 IN SCMI_PROTOCOL_ID ProtocolId,
246 OUT UINT32 **ReturnValues
247 )
248 {
249 return ScmiProtocolDiscoveryCommon (
250 ProtocolId,
251 ScmiMessageIdProtocolMessageAttributes,
252 ReturnValues
253 );
254 }