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