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