TianoCore EDK2 master
Loading...
Searching...
No Matches
ScmiClockProtocol.c
Go to the documentation of this file.
1
12#include <Library/BaseLib.h>
13#include <Library/DebugLib.h>
17
19#include "ScmiPrivate.h"
20
29UINT64
31 IN UINT32 Low,
32 IN UINT32 High
33 )
34{
35 return (Low | ((UINT64)High << 32));
36}
37
52 OUT UINT32 *Version
53 )
54{
55 return ScmiGetProtocolVersion (ScmiProtocolIdClock, Version);
56}
57
73 OUT UINT32 *TotalClocks
74 )
75{
76 EFI_STATUS Status;
77 UINT32 *ReturnValues;
78
79 Status = ScmiGetProtocolAttributes (ScmiProtocolIdClock, &ReturnValues);
80 if (EFI_ERROR (Status)) {
81 return Status;
82 }
83
84 *TotalClocks = SCMI_CLOCK_PROTOCOL_TOTAL_CLKS (ReturnValues[0]);
85
86 return EFI_SUCCESS;
87}
88
102STATIC
106 IN UINT32 ClockId,
107 OUT BOOLEAN *Enabled,
108 OUT CHAR8 *ClockAsciiName
109 )
110{
111 EFI_STATUS Status;
112
113 UINT32 *MessageParams;
114 CLOCK_ATTRIBUTES *ClockAttributes;
115 SCMI_COMMAND Cmd;
116 UINT32 PayloadLength;
117
118 Status = ScmiCommandGetPayload (&MessageParams);
119 if (EFI_ERROR (Status)) {
120 return Status;
121 }
122
123 *MessageParams = ClockId;
124
125 Cmd.ProtocolId = ScmiProtocolIdClock;
126 Cmd.MessageId = ScmiMessageIdClockAttributes;
127
128 PayloadLength = sizeof (ClockId);
129
130 Status = ScmiCommandExecute (
131 &Cmd,
132 &PayloadLength,
133 (UINT32 **)&ClockAttributes
134 );
135 if (EFI_ERROR (Status)) {
136 return Status;
137 }
138
139 // TRUE if bit 0 of ClockAttributes->Attributes is set.
140 *Enabled = CLOCK_ENABLED (ClockAttributes->Attributes);
141
143 ClockAsciiName,
144 SCMI_MAX_STR_LEN,
145 (CONST CHAR8 *)ClockAttributes->ClockName
146 );
147
148 return EFI_SUCCESS;
149}
150
174STATIC
178 IN UINT32 ClockId,
179 OUT SCMI_CLOCK_RATE_FORMAT *Format,
180 OUT UINT32 *TotalRates,
181 IN OUT UINT32 *RateArraySize,
182 OUT SCMI_CLOCK_RATE *RateArray
183 )
184{
185 EFI_STATUS Status;
186
187 UINT32 PayloadLength;
188 SCMI_COMMAND Cmd;
189 UINT32 *MessageParams;
190 CLOCK_DESCRIBE_RATES *DescribeRates;
191 CLOCK_RATE_DWORD *Rate;
192
193 UINT32 RequiredArraySize;
194 UINT32 RateIndex;
195 UINT32 RateNo;
196 UINT32 RateOffset;
197
198 *TotalRates = 0;
199 RequiredArraySize = 0;
200 RateIndex = 0;
201
202 Status = ScmiCommandGetPayload (&MessageParams);
203 if (EFI_ERROR (Status)) {
204 return Status;
205 }
206
207 Cmd.ProtocolId = ScmiProtocolIdClock;
208 Cmd.MessageId = ScmiMessageIdClockDescribeRates;
209
210 *MessageParams++ = ClockId;
211
212 do {
213 *MessageParams = RateIndex;
214
215 // Set Payload length, note PayloadLength is a IN/OUT parameter.
216 PayloadLength = sizeof (ClockId) + sizeof (RateIndex);
217
218 // Execute and wait for response on a SCMI channel.
219 Status = ScmiCommandExecute (
220 &Cmd,
221 &PayloadLength,
222 (UINT32 **)&DescribeRates
223 );
224 if (EFI_ERROR (Status)) {
225 return Status;
226 }
227
228 if (*TotalRates == 0) {
229 // In the first iteration we will get number of returned rates and number
230 // of remaining rates. With this information calculate required size
231 // for rate array. If provided RateArraySize is less, return an
232 // error.
233
234 *Format = RATE_FORMAT (DescribeRates->NumRatesFlags);
235
236 *TotalRates = NUM_RATES (DescribeRates->NumRatesFlags)
237 + NUM_REMAIN_RATES (DescribeRates->NumRatesFlags);
238
239 RequiredArraySize = (*TotalRates) * sizeof (UINT64);
240
241 if (RequiredArraySize > (*RateArraySize)) {
242 *RateArraySize = RequiredArraySize;
243 return EFI_BUFFER_TOO_SMALL;
244 }
245 }
246
247 RateOffset = 0;
248
249 if (*Format == ScmiClockRateFormatDiscrete) {
250 for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) {
251 Rate = &DescribeRates->Rates[RateOffset++];
252 // Non-linear discrete rates.
253 RateArray[RateIndex++].DiscreteRate.Rate =
254 ConvertTo64Bit (Rate->Low, Rate->High);
255 }
256 } else {
257 // Linear clock rates from minimum to maximum in steps
258 // Minimum clock rate.
259 Rate = &DescribeRates->Rates[RateOffset++];
260 RateArray[RateIndex].ContinuousRate.Min =
261 ConvertTo64Bit (Rate->Low, Rate->High);
262
263 Rate = &DescribeRates->Rates[RateOffset++];
264 // Maximum clock rate.
265 RateArray[RateIndex].ContinuousRate.Max =
266 ConvertTo64Bit (Rate->Low, Rate->High);
267
268 Rate = &DescribeRates->Rates[RateOffset++];
269 // Step.
270 RateArray[RateIndex++].ContinuousRate.Step =
271 ConvertTo64Bit (Rate->Low, Rate->High);
272 }
273 } while (NUM_REMAIN_RATES (DescribeRates->NumRatesFlags) != 0);
274
275 // Update RateArraySize with RequiredArraySize.
276 *RateArraySize = RequiredArraySize;
277
278 return EFI_SUCCESS;
279}
280
292STATIC
296 IN UINT32 ClockId,
297 OUT UINT64 *Rate
298 )
299{
300 EFI_STATUS Status;
301
302 UINT32 *MessageParams;
303 CLOCK_RATE_DWORD *ClockRate;
304 SCMI_COMMAND Cmd;
305
306 UINT32 PayloadLength;
307
308 Status = ScmiCommandGetPayload (&MessageParams);
309 if (EFI_ERROR (Status)) {
310 return Status;
311 }
312
313 // Fill arguments for clock protocol command.
314 *MessageParams = ClockId;
315
316 Cmd.ProtocolId = ScmiProtocolIdClock;
317 Cmd.MessageId = ScmiMessageIdClockRateGet;
318
319 PayloadLength = sizeof (ClockId);
320
321 // Execute and wait for response on a SCMI channel.
322 Status = ScmiCommandExecute (
323 &Cmd,
324 &PayloadLength,
325 (UINT32 **)&ClockRate
326 );
327 if (EFI_ERROR (Status)) {
328 return Status;
329 }
330
331 *Rate = ConvertTo64Bit (ClockRate->Low, ClockRate->High);
332
333 return EFI_SUCCESS;
334}
335
346STATIC
350 IN UINT32 ClockId,
351 IN UINT64 Rate
352 )
353{
354 EFI_STATUS Status;
355 CLOCK_RATE_SET_ATTRIBUTES *ClockRateSetAttributes;
356 SCMI_COMMAND Cmd;
357 UINT32 PayloadLength;
358
359 Status = ScmiCommandGetPayload ((UINT32 **)&ClockRateSetAttributes);
360 if (EFI_ERROR (Status)) {
361 return Status;
362 }
363
364 // Fill arguments for clock protocol command.
365 ClockRateSetAttributes->ClockId = ClockId;
366 ClockRateSetAttributes->Flags = CLOCK_SET_DEFAULT_FLAGS;
367 ClockRateSetAttributes->Rate.Low = (UINT32)Rate;
368 ClockRateSetAttributes->Rate.High = (UINT32)(Rate >> 32);
369
370 Cmd.ProtocolId = ScmiProtocolIdClock;
371 Cmd.MessageId = ScmiMessageIdClockRateSet;
372
373 PayloadLength = sizeof (CLOCK_RATE_SET_ATTRIBUTES);
374
375 // Execute and wait for response on a SCMI channel.
376 Status = ScmiCommandExecute (
377 &Cmd,
378 &PayloadLength,
379 NULL
380 );
381
382 return Status;
383}
384
395STATIC
399 IN UINT32 ClockId,
400 IN BOOLEAN Enable
401 )
402{
403 EFI_STATUS Status;
404 CLOCK_CONFIG_SET_ATTRIBUTES *ClockConfigSetAttributes;
405 SCMI_COMMAND Cmd;
406 UINT32 PayloadLength;
407
408 Status = ScmiCommandGetPayload ((UINT32 **)&ClockConfigSetAttributes);
409 if (EFI_ERROR (Status)) {
410 return Status;
411 }
412
413 // Fill arguments for clock protocol command.
414 ClockConfigSetAttributes->ClockId = ClockId;
415 ClockConfigSetAttributes->Attributes = Enable ? BIT0 : 0;
416
417 Cmd.ProtocolId = ScmiProtocolIdClock;
418 Cmd.MessageId = ScmiMessageIdClockConfigSet;
419
420 PayloadLength = sizeof (CLOCK_CONFIG_SET_ATTRIBUTES);
421
422 // Execute and wait for response on a SCMI channel.
423 Status = ScmiCommandExecute (
424 &Cmd,
425 &PayloadLength,
426 NULL
427 );
428
429 return Status;
430}
431
432// Instance of the SCMI clock management protocol.
433STATIC CONST SCMI_CLOCK_PROTOCOL ScmiClockProtocol = {
440};
441
442// Instance of the SCMI clock management protocol.
443STATIC CONST SCMI_CLOCK2_PROTOCOL ScmiClock2Protocol = {
450 SCMI_CLOCK2_PROTOCOL_VERSION,
452};
453
462 IN EFI_HANDLE *Handle
463 )
464{
465 return gBS->InstallMultipleProtocolInterfaces (
466 Handle,
467 &gArmScmiClockProtocolGuid,
468 &ScmiClockProtocol,
469 &gArmScmiClock2ProtocolGuid,
470 &ScmiClock2Protocol,
471 NULL
472 );
473}
EFI_STATUS(EFIAPI * SCMI_CLOCK2_RATE_GET)(IN SCMI_CLOCK2_PROTOCOL *This, IN UINT32 ClockId, OUT UINT64 *Rate)
EFI_STATUS(EFIAPI * SCMI_CLOCK2_DESCRIBE_RATES)(IN SCMI_CLOCK2_PROTOCOL *This, IN UINT32 ClockId, OUT SCMI_CLOCK_RATE_FORMAT *Format, OUT UINT32 *TotalRates, IN OUT UINT32 *RateArraySize, OUT SCMI_CLOCK_RATE *RateArray)
EFI_STATUS(EFIAPI * SCMI_CLOCK2_GET_CLOCK_ATTRIBUTES)(IN SCMI_CLOCK2_PROTOCOL *This, IN UINT32 ClockId, OUT BOOLEAN *Enabled, OUT CHAR8 *ClockAsciiName)
EFI_STATUS(EFIAPI * SCMI_CLOCK2_GET_VERSION)(IN SCMI_CLOCK2_PROTOCOL *This, OUT UINT32 *Version)
EFI_STATUS(EFIAPI * SCMI_CLOCK2_GET_TOTAL_CLOCKS)(IN SCMI_CLOCK2_PROTOCOL *This, OUT UINT32 *TotalClocks)
EFI_STATUS(EFIAPI * SCMI_CLOCK2_RATE_SET)(IN SCMI_CLOCK2_PROTOCOL *This, IN UINT32 ClockId, IN UINT64 Rate)
RETURN_STATUS EFIAPI AsciiStrCpyS(OUT CHAR8 *Destination, IN UINTN DestMax, IN CONST CHAR8 *Source)
Definition: SafeString.c:1797
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_STATUS ScmiGetProtocolVersion(IN SCMI_PROTOCOL_ID ProtocolId, OUT UINT32 *Version)
Definition: Scmi.c:190
EFI_STATUS ScmiCommandExecute(IN SCMI_COMMAND *Command, IN OUT UINT32 *PayloadLength, OUT UINT32 **ReturnValues OPTIONAL)
Definition: Scmi.c:76
EFI_STATUS ScmiCommandGetPayload(OUT UINT32 **Payload)
Definition: Scmi.c:31
EFI_STATUS ScmiGetProtocolAttributes(IN SCMI_PROTOCOL_ID ProtocolId, OUT UINT32 **ReturnValues)
Definition: Scmi.c:222
STATIC UINT64 ConvertTo64Bit(IN UINT32 Low, IN UINT32 High)
STATIC EFI_STATUS ClockRateGet(IN SCMI_CLOCK_PROTOCOL *This, IN UINT32 ClockId, OUT UINT64 *Rate)
STATIC EFI_STATUS ClockRateSet(IN SCMI_CLOCK_PROTOCOL *This, IN UINT32 ClockId, IN UINT64 Rate)
STATIC EFI_STATUS ClockDescribeRates(IN SCMI_CLOCK_PROTOCOL *This, IN UINT32 ClockId, OUT SCMI_CLOCK_RATE_FORMAT *Format, OUT UINT32 *TotalRates, IN OUT UINT32 *RateArraySize, OUT SCMI_CLOCK_RATE *RateArray)
STATIC EFI_STATUS ClockEnable(IN SCMI_CLOCK2_PROTOCOL *This, IN UINT32 ClockId, IN BOOLEAN Enable)
STATIC EFI_STATUS ClockGetTotalClocks(IN SCMI_CLOCK_PROTOCOL *This, OUT UINT32 *TotalClocks)
STATIC EFI_STATUS ClockGetVersion(IN SCMI_CLOCK_PROTOCOL *This, OUT UINT32 *Version)
EFI_STATUS ScmiClockProtocolInit(IN EFI_HANDLE *Handle)
STATIC EFI_STATUS ClockGetClockAttributes(IN SCMI_CLOCK_PROTOCOL *This, IN UINT32 ClockId, OUT BOOLEAN *Enabled, OUT CHAR8 *ClockAsciiName)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS