]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
e012424a9bb58d5ddb095ac54244d658f45acd10
[mirror_edk2.git] / ArmPkg / Drivers / ArmScmiDxe / ScmiPerformanceProtocol.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/BaseMemoryLib.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Protocol/ArmScmiPerformanceProtocol.h>
21
22 #include "ArmScmiPerformanceProtocolPrivate.h"
23 #include "ScmiPrivate.h"
24
25 /** Return version of the performance management protocol supported by SCP.
26 firmware.
27
28 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
29
30 @param[out] Version Version of the supported SCMI performance management
31 protocol.
32
33 @retval EFI_SUCCESS The version is returned.
34 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
35 @retval !(EFI_SUCCESS) Other errors.
36 **/
37 STATIC
38 EFI_STATUS
39 PerformanceGetVersion (
40 IN SCMI_PERFORMANCE_PROTOCOL *This,
41 OUT UINT32 *Version
42 )
43 {
44 return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_PERFORMANCE, Version);
45 }
46
47 /** Return protocol attributes of the performance management protocol.
48
49 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
50
51 @param[out] Attributes Protocol attributes.
52
53 @retval EFI_SUCCESS Protocol attributes are returned.
54 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
55 @retval !(EFI_SUCCESS) Other errors.
56 **/
57 STATIC
58 EFI_STATUS
59 PerformanceGetAttributes (
60 IN SCMI_PERFORMANCE_PROTOCOL *This,
61 OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES *Attributes
62 )
63 {
64 EFI_STATUS Status;
65 UINT32* ReturnValues;
66
67 Status = ScmiGetProtocolAttributes (
68 SCMI_PROTOCOL_ID_PERFORMANCE,
69 &ReturnValues
70 );
71 if (EFI_ERROR (Status)) {
72 return Status;
73 }
74
75 CopyMem (
76 Attributes,
77 ReturnValues,
78 sizeof (SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES)
79 );
80
81 return EFI_SUCCESS;
82 }
83
84 /** Return performance domain attributes.
85
86 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
87 @param[in] DomainId Identifier for the performance domain.
88
89 @param[out] Attributes Performance domain attributes.
90
91 @retval EFI_SUCCESS Domain attributes are returned.
92 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
93 @retval !(EFI_SUCCESS) Other errors.
94 **/
95 STATIC
96 EFI_STATUS
97 PerformanceDomainAttributes (
98 IN SCMI_PERFORMANCE_PROTOCOL *This,
99 IN UINT32 DomainId,
100 OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES *DomainAttributes
101 )
102 {
103 EFI_STATUS Status;
104 UINT32 *MessageParams;
105 UINT32 *ReturnValues;
106 UINT32 PayloadLength;
107 SCMI_COMMAND Cmd;
108
109 Status = ScmiCommandGetPayload (&MessageParams);
110 if (EFI_ERROR (Status)) {
111 return Status;
112 }
113
114 *MessageParams = DomainId;
115
116 Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE;
117 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_DOMAIN_ATTRIBUTES;
118
119 PayloadLength = sizeof (DomainId);
120
121 Status = ScmiCommandExecute (
122 &Cmd,
123 &PayloadLength,
124 &ReturnValues
125 );
126 if (EFI_ERROR (Status)) {
127 return Status;
128 }
129
130 CopyMem (
131 DomainAttributes,
132 ReturnValues,
133 sizeof (SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES)
134 );
135
136 return EFI_SUCCESS;
137 }
138
139 /** Return list of performance domain levels of a given domain.
140
141 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
142 @param[in] DomainId Identifier for the performance domain.
143
144 @param[out] NumLevels Total number of levels a domain can support.
145
146 @param[in,out] LevelArraySize Size of the performance level array.
147
148 @param[out] LevelArray Array of the performance levels.
149
150 @retval EFI_SUCCESS Domain levels are returned.
151 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
152 @retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result.
153 It has been updated to the size needed.
154 @retval !(EFI_SUCCESS) Other errors.
155 **/
156 STATIC
157 EFI_STATUS
158 PerformanceDescribeLevels (
159 IN SCMI_PERFORMANCE_PROTOCOL *This,
160 IN UINT32 DomainId,
161 OUT UINT32 *NumLevels,
162 IN OUT UINT32 *LevelArraySize,
163 OUT SCMI_PERFORMANCE_LEVEL *LevelArray
164 )
165 {
166 EFI_STATUS Status;
167 UINT32 PayloadLength;
168 SCMI_COMMAND Cmd;
169 UINT32* MessageParams;
170 UINT32 LevelIndex;
171 UINT32 RequiredSize;
172 UINT32 LevelNo;
173 UINT32 ReturnNumLevels;
174 UINT32 ReturnRemainNumLevels;
175
176 PERF_DESCRIBE_LEVELS *Levels;
177
178 Status = ScmiCommandGetPayload (&MessageParams);
179 if (EFI_ERROR (Status)) {
180 return Status;
181 }
182
183 LevelIndex = 0;
184 RequiredSize = 0;
185
186 *MessageParams++ = DomainId;
187
188 Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE;
189 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS;
190
191 do {
192
193 *MessageParams = LevelIndex;
194
195 // Note, PayloadLength is an IN/OUT parameter.
196 PayloadLength = sizeof (DomainId) + sizeof (LevelIndex);
197
198 Status = ScmiCommandExecute (
199 &Cmd,
200 &PayloadLength,
201 (UINT32**)&Levels
202 );
203 if (EFI_ERROR (Status)) {
204 return Status;
205 }
206
207 ReturnNumLevels = NUM_PERF_LEVELS (Levels->NumLevels);
208 ReturnRemainNumLevels = NUM_REMAIN_PERF_LEVELS (Levels->NumLevels);
209
210 if (RequiredSize == 0) {
211 *NumLevels = ReturnNumLevels + ReturnRemainNumLevels;
212
213 RequiredSize = (*NumLevels) * sizeof (SCMI_PERFORMANCE_LEVEL);
214 if (RequiredSize > (*LevelArraySize)) {
215 // Update LevelArraySize with required size.
216 *LevelArraySize = RequiredSize;
217 return EFI_BUFFER_TOO_SMALL;
218 }
219 }
220
221 for (LevelNo = 0; LevelNo < ReturnNumLevels; LevelNo++) {
222 CopyMem (
223 &LevelArray[LevelIndex++],
224 &Levels->PerfLevel[LevelNo],
225 sizeof (SCMI_PERFORMANCE_LEVEL)
226 );
227 }
228
229 } while (ReturnRemainNumLevels != 0);
230
231 *LevelArraySize = RequiredSize;
232
233 return EFI_SUCCESS;
234 }
235
236 /** Set performance limits of a domain.
237
238 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
239 @param[in] DomainId Identifier for the performance domain.
240 @param[in] Limit Performance limit to set.
241
242 @retval EFI_SUCCESS Performance limits set successfully.
243 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
244 @retval !(EFI_SUCCESS) Other errors.
245 **/
246 EFI_STATUS
247 PerformanceLimitsSet (
248 IN SCMI_PERFORMANCE_PROTOCOL *This,
249 IN UINT32 DomainId,
250 IN SCMI_PERFORMANCE_LIMITS *Limits
251 )
252 {
253 EFI_STATUS Status;
254 UINT32 PayloadLength;
255 SCMI_COMMAND Cmd;
256 UINT32 *MessageParams;
257
258 Status = ScmiCommandGetPayload (&MessageParams);
259 if (EFI_ERROR (Status)) {
260 return Status;
261 }
262
263 *MessageParams++ = DomainId;
264 *MessageParams++ = Limits->RangeMax;
265 *MessageParams = Limits->RangeMin;
266
267 Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE;
268 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET;
269
270 PayloadLength = sizeof (DomainId) + sizeof (SCMI_PERFORMANCE_LIMITS);
271
272 Status = ScmiCommandExecute (
273 &Cmd,
274 &PayloadLength,
275 NULL
276 );
277
278 return Status;
279 }
280
281 /** Get performance limits of a domain.
282
283 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
284 @param[in] DomainId Identifier for the performance domain.
285
286 @param[out] Limit Performance Limits of the domain.
287
288 @retval EFI_SUCCESS Performance limits are returned.
289 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
290 @retval !(EFI_SUCCESS) Other errors.
291 **/
292 EFI_STATUS
293 PerformanceLimitsGet (
294 SCMI_PERFORMANCE_PROTOCOL *This,
295 UINT32 DomainId,
296 SCMI_PERFORMANCE_LIMITS *Limits
297 )
298 {
299 EFI_STATUS Status;
300 UINT32 PayloadLength;
301 SCMI_COMMAND Cmd;
302 UINT32 *MessageParams;
303
304 SCMI_PERFORMANCE_LIMITS *ReturnValues;
305
306 Status = ScmiCommandGetPayload (&MessageParams);
307 if (EFI_ERROR (Status)) {
308 return Status;
309 }
310
311 *MessageParams = DomainId;
312
313 Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE;
314 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET;
315
316 PayloadLength = sizeof (DomainId);
317
318 Status = ScmiCommandExecute (
319 &Cmd,
320 &PayloadLength,
321 (UINT32**)&ReturnValues
322 );
323 if (EFI_ERROR (Status)) {
324 return Status;
325 }
326
327 Limits->RangeMax = ReturnValues->RangeMax;
328 Limits->RangeMin = ReturnValues->RangeMin;
329
330 return EFI_SUCCESS;
331 }
332
333 /** Set performance level of a domain.
334
335 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
336 @param[in] DomainId Identifier for the performance domain.
337 @param[in] Level Performance level of the domain.
338
339 @retval EFI_SUCCESS Performance level set successfully.
340 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
341 @retval !(EFI_SUCCESS) Other errors.
342 **/
343 EFI_STATUS
344 PerformanceLevelSet (
345 IN SCMI_PERFORMANCE_PROTOCOL *This,
346 IN UINT32 DomainId,
347 IN UINT32 Level
348 )
349 {
350 EFI_STATUS Status;
351 UINT32 PayloadLength;
352 SCMI_COMMAND Cmd;
353 UINT32 *MessageParams;
354
355 Status = ScmiCommandGetPayload (&MessageParams);
356 if (EFI_ERROR (Status)) {
357 return Status;
358 }
359
360 *MessageParams++ = DomainId;
361 *MessageParams = Level;
362
363 Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE;
364 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET;
365
366 PayloadLength = sizeof (DomainId) + sizeof (Level);
367
368 Status = ScmiCommandExecute (
369 &Cmd,
370 &PayloadLength,
371 NULL
372 );
373
374 return Status;
375 }
376
377 /** Get performance level of a domain.
378
379 @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
380 @param[in] DomainId Identifier for the performance domain.
381
382 @param[out] Level Performance level of the domain.
383
384 @retval EFI_SUCCESS Performance level got successfully.
385 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
386 @retval !(EFI_SUCCESS) Other errors.
387 **/
388 EFI_STATUS
389 PerformanceLevelGet (
390 IN SCMI_PERFORMANCE_PROTOCOL *This,
391 IN UINT32 DomainId,
392 OUT UINT32 *Level
393 )
394 {
395 EFI_STATUS Status;
396 UINT32 PayloadLength;
397 SCMI_COMMAND Cmd;
398 UINT32 *ReturnValues;
399 UINT32 *MessageParams;
400
401 Status = ScmiCommandGetPayload (&MessageParams);
402 if (EFI_ERROR (Status)) {
403 return Status;
404 }
405
406 *MessageParams = DomainId;
407
408 Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE;
409 Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET;
410
411 PayloadLength = sizeof (DomainId);
412
413 Status = ScmiCommandExecute (
414 &Cmd,
415 &PayloadLength,
416 &ReturnValues
417 );
418 if (EFI_ERROR (Status)) {
419 return Status;
420 }
421
422 *Level = *ReturnValues;
423
424 return EFI_SUCCESS;
425 }
426
427 // Instance of the SCMI performance management protocol.
428 STATIC CONST SCMI_PERFORMANCE_PROTOCOL PerformanceProtocol = {
429 PerformanceGetVersion,
430 PerformanceGetAttributes,
431 PerformanceDomainAttributes,
432 PerformanceDescribeLevels,
433 PerformanceLimitsSet,
434 PerformanceLimitsGet,
435 PerformanceLevelSet,
436 PerformanceLevelGet
437 };
438
439 /** Initialize performance management protocol and install on a given Handle.
440
441 @param[in] Handle Handle to install performance management
442 protocol.
443
444 @retval EFI_SUCCESS Performance protocol installed successfully.
445 **/
446 EFI_STATUS
447 ScmiPerformanceProtocolInit (
448 IN EFI_HANDLE* Handle
449 )
450 {
451 return gBS->InstallMultipleProtocolInterfaces (
452 Handle,
453 &gArmScmiPerformanceProtocolGuid,
454 &PerformanceProtocol,
455 NULL
456 );
457 }