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