diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec index 3be5f13f8f..debe066b6f 100644 --- a/ArmPkg/ArmPkg.dec +++ b/ArmPkg/ArmPkg.dec @@ -49,6 +49,19 @@ # Include/Guid/ArmMpCoreInfo.h gArmMpCoreInfoGuid = { 0xa4ee0728, 0xe5d7, 0x4ac5, {0xb2, 0x1e, 0x65, 0x8e, 0xd8, 0x57, 0xe8, 0x34} } +[Protocols.common] + ## Arm System Control and Management Interface(SCMI) Base protocol + ## ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h + gArmScmiBaseProtocolGuid = { 0xd7e5abe9, 0x33ab, 0x418e, { 0x9f, 0x91, 0x72, 0xda, 0xe2, 0xba, 0x8e, 0x2f } } + + ## Arm System Control and Management Interface(SCMI) Clock management protocol + ## ArmPkg/Include/Protocol/ArmScmiClockProtocol.h + gArmScmiClockProtocolGuid = { 0x91ce67a8, 0xe0aa, 0x4012, { 0xb9, 0x9f, 0xb6, 0xfc, 0xf3, 0x4, 0x8e, 0xaa } } + + ## Arm System Control and Management Interface(SCMI) Clock management protocol + ## ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h + gArmScmiPerformanceProtocolGuid = { 0x9b8ba84, 0x3dd3, 0x49a6, { 0xa0, 0x5a, 0x31, 0x34, 0xa5, 0xf0, 0x7b, 0xad } } + [Ppis] ## Include/Ppi/ArmMpCoreInfo.h gArmMpCoreInfoPpiGuid = { 0x6847cc74, 0xe9ec, 0x4f8f, {0xa2, 0x9d, 0xab, 0x44, 0xe7, 0x54, 0xa8, 0xfc} } diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc index 526909458e..22332090db 100644 --- a/ArmPkg/ArmPkg.dsc +++ b/ArmPkg/ArmPkg.dsc @@ -2,7 +2,7 @@ # ARM processor package. # # Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
-# Copyright (c) 2011 - 2015, ARM Ltd. All rights reserved.
+# Copyright (c) 2011 - 2018, ARM Ltd. All rights reserved.
# Copyright (c) 2016, Linaro Ltd. All rights reserved.
# # This program and the accompanying materials @@ -87,6 +87,8 @@ ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf + ArmMtlLib|ArmPkg/Library/ArmMtlNullLib/ArmMtlNullLib.inf + [LibraryClasses.common.PEIM] HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf @@ -144,5 +146,7 @@ ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf + ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf + [Components.AARCH64] ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf diff --git a/ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h new file mode 100644 index 0000000000..79c057d441 --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h @@ -0,0 +1,46 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#ifndef ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_ +#define ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_ + +// Return values of BASE_DISCOVER_LIST_PROTOCOLS command. +typedef struct { + UINT32 NumProtocols; + + // Array of four protocols in each element + // Total elements = 1 + (NumProtocols-1)/4 + + // NOTE: Since EDK2 does not allow flexible array member [] we declare + // here array of 1 element length. However below is used as a variable + // length array. + UINT8 Protocols[1]; +} BASE_DISCOVER_LIST; + +/** Initialize Base protocol and install protocol on a given handle. + + @param[in] Handle Handle to install Base protocol. + + @retval EFI_SUCCESS Base protocol interface installed + successfully. +**/ +EFI_STATUS +ScmiBaseProtocolInit ( + IN OUT EFI_HANDLE* Handle + ); + +#endif /* ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_ */ diff --git a/ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h new file mode 100644 index 0000000000..0d1ec6f5ad --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h @@ -0,0 +1,84 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#ifndef ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_ +#define ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_ + +#pragma pack(1) + +// Clock rate in two 32bit words. +typedef struct { + UINT32 Low; + UINT32 High; +} CLOCK_RATE_DWORD; + +// Format of the returned rate array. Linear or Non-linear,.RatesFlag Bit[12] +#define RATE_FORMAT_SHIFT 12 +#define RATE_FORMAT_MASK 0x0001 +#define RATE_FORMAT(RatesFlags) ((RatesFlags >> RATE_FORMAT_SHIFT) \ + & RATE_FORMAT_MASK) + +// Number of remaining rates after a call to the SCP, RatesFlag Bits[31:16] +#define NUM_REMAIN_RATES_SHIFT 16 +#define NUM_REMAIN_RATES(RatesFlags) ((RatesFlags >> NUM_REMAIN_RATES_SHIFT)) + +// Number of rates that are returned by a call.to the SCP, RatesFlag Bits[11:0] +#define NUM_RATES_MASK 0x0FFF +#define NUM_RATES(RatesFlags) (RatesFlags & NUM_RATES_MASK) + +// Return values for the CLOCK_DESCRIBER_RATE command. +typedef struct { + UINT32 NumRatesFlags; + + // NOTE: Since EDK2 does not allow flexible array member [] we declare + // here array of 1 element length. However below is used as a variable + // length array. + CLOCK_RATE_DWORD Rates[1]; +} CLOCK_DESCRIBE_RATES; + +#define CLOCK_SET_DEFAULT_FLAGS 0 + +// Message parameters for CLOCK_RATE_SET command. +typedef struct { + UINT32 Flags; + UINT32 ClockId; + CLOCK_RATE_DWORD Rate; +} CLOCK_RATE_SET_ATTRIBUTES; + +// if ClockAttr Bit[0] is set then clock device is enabled. +#define CLOCK_ENABLE_MASK 0x1 +#define CLOCK_ENABLED(ClockAttr) ((ClockAttr & CLOCK_ENABLE_MASK) == 1) + +typedef struct { + UINT32 Attributes; + UINT8 ClockName[SCMI_MAX_STR_LEN]; +} CLOCK_ATTRIBUTES; + +#pragma pack() + +/** Initialize clock management protocol and install protocol on a given handle. + + @param[in] Handle Handle to install clock management protocol. + + @retval EFI_SUCCESS Clock protocol interface installed successfully. +**/ +EFI_STATUS +ScmiClockProtocolInit ( + IN EFI_HANDLE *Handle + ); + +#endif /* ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_ */ diff --git a/ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf new file mode 100644 index 0000000000..05ce9c04ce --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf @@ -0,0 +1,53 @@ +#/** @file +# +# Copyright (c) 2017-2018, Arm Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# System Control and Management Interface V1.0 +# http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ +# DEN0056A_System_Control_and_Management_Interface.pdf +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = ArmScmiDxe + FILE_GUID = 9585984C-F027-45E9-AFDF-ADAA6DFAAAC7 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = ArmScmiDxeEntryPoint + +[Sources.common] + Scmi.c + ScmiBaseProtocol.c + ScmiClockProtocol.c + ScmiDxe.c + ScmiPerformanceProtocol.c + +[Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmLib + ArmMtlLib + DebugLib + IoLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gArmScmiBaseProtocolGuid + gArmScmiClockProtocolGuid + gArmScmiPerformanceProtocolGuid + +[Depex] + TRUE + diff --git a/ArmPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h new file mode 100644 index 0000000000..4514f45a9f --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h @@ -0,0 +1,55 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#ifndef ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ +#define ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ + +#include + +// Number of performance levels returned by a call to the SCP, Lvls Bits[11:0] +#define NUM_PERF_LEVELS_MASK 0x0FFF +#define NUM_PERF_LEVELS(Lvls) (Lvls & NUM_PERF_LEVELS_MASK) + +// Number of performance levels remaining after a call to the SCP, Lvls Bits[31:16] +#define NUM_REMAIN_PERF_LEVELS_SHIFT 16 +#define NUM_REMAIN_PERF_LEVELS(Lvls) (Lvls >> NUM_REMAIN_PERF_LEVELS_SHIFT) + +/** Return values for SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS command. + SCMI Spec § 4.5.2.5 +**/ +typedef struct { + UINT32 NumLevels; + + // NOTE: Since EDK2 does not allow flexible array member [] we declare + // here array of 1 element length. However below is used as a variable + // length array. + SCMI_PERFORMANCE_LEVEL PerfLevel[1]; // Offset to array of performance levels +} PERF_DESCRIBE_LEVELS; + +/** Initialize performance management protocol and install on a given Handle. + + @param[in] Handle Handle to install performance management + protocol. + + @retval EFI_SUCCESS Performance protocol installed successfully. +**/ +EFI_STATUS +ScmiPerformanceProtocolInit ( + IN EFI_HANDLE* Handle + ); + +#endif /* ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ */ diff --git a/ArmPkg/Drivers/ArmScmiDxe/Scmi.c b/ArmPkg/Drivers/ArmScmiDxe/Scmi.c new file mode 100644 index 0000000000..1e279f69cf --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/Scmi.c @@ -0,0 +1,262 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#include +#include +#include +#include + +#include "ScmiPrivate.h" + +// SCMI Specification 1.0 +#define MAX_PROTOCOLS 6 + +#define PROTOCOL_MASK 0xF + +// Arbitrary timeout value 20ms. +#define RESPONSE_TIMEOUT 20000 + +/** Return a pointer to the message payload. + + @param[out] Payload Holds pointer to the message payload. + + @retval EFI_SUCCESS Payload holds a valid message payload pointer. + @retval EFI_TIMEOUT Time out error if MTL channel is busy. + @retval EFI_UNSUPPORTED If MTL channel is unsupported. +**/ +EFI_STATUS +ScmiCommandGetPayload ( + OUT UINT32** Payload + ) +{ + EFI_STATUS Status; + MTL_CHANNEL *Channel; + + // Get handle to the Channel. + Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel); + if (EFI_ERROR (Status)) { + return Status; + } + + // Payload will not be populated until channel is free. + Status = MtlWaitUntilChannelFree (Channel, RESPONSE_TIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + // Get the address of the payload. + *Payload = MtlGetChannelPayload (Channel); + + return EFI_SUCCESS; +} + +/** Execute a SCMI command and receive a response. + + This function uses a MTL channel to transfer message to SCP + and waits for a response. + + @param[in] Command Pointer to the SCMI command (Protocol ID + and Message ID) + + @param[in,out] PayloadLength SCMI command message length. + + @param[out] OPTIONAL ReturnValues Pointer to SCMI response. + + @retval OUT EFI_SUCCESS Command sent and message received successfully. + @retval OUT EFI_UNSUPPORTED Channel not supported. + @retval OUT EFI_TIMEOUT Timeout on the channel. + @retval OUT EFI_DEVICE_ERROR Channel not ready. + @retval OUT EFI_DEVICE_ERROR Message Header corrupted. + @retval OUT EFI_DEVICE_ERROR SCMI error. +**/ +EFI_STATUS +ScmiCommandExecute ( + IN SCMI_COMMAND *Command, + IN OUT UINT32 *PayloadLength, + OUT UINT32 **ReturnValues OPTIONAL + ) +{ + EFI_STATUS Status; + SCMI_MESSAGE_RESPONSE *Response; + UINT32 MessageHeader; + UINT32 ResponseHeader; + MTL_CHANNEL *Channel; + + ASSERT (PayloadLength != NULL); + + Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel); + if (EFI_ERROR (Status)) { + return Status; + } + + // Fill in message header. + MessageHeader = SCMI_MESSAGE_HEADER ( + Command->MessageId, + SCMI_MESSAGE_TYPE_COMMAND, + Command->ProtocolId + ); + + // Send payload using MTL channel. + Status = MtlSendMessage ( + Channel, + MessageHeader, + *PayloadLength + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Wait for the response on the channel. + Status = MtlReceiveMessage (Channel, &ResponseHeader, PayloadLength); + if (EFI_ERROR (Status)) { + return Status; + } + + // SCMI must return MessageHeader unmodified. + if (MessageHeader != ResponseHeader) { + ASSERT (FALSE); + return EFI_DEVICE_ERROR; + } + + Response = (SCMI_MESSAGE_RESPONSE*)MtlGetChannelPayload (Channel); + + if (Response->Status != SCMI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "SCMI error: ProtocolId = 0x%x, MessageId = 0x%x, error = %d\n", + Command->ProtocolId, + Command->MessageId, + Response->Status + )); + + ASSERT (FALSE); + return EFI_DEVICE_ERROR; + } + + if (ReturnValues != NULL) { + *ReturnValues = Response->ReturnValues; + } + + return EFI_SUCCESS; +} + +/** Internal common function useful for common protocol discovery messages. + + @param[in] ProtocolId Protocol Id of the the protocol. + @param[in] MesaageId Message Id of the message. + + @param[out] ReturnValues SCMI response return values. + + @retval EFI_SUCCESS Success with valid return values. + @retval EFI_DEVICE_ERROR SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +ScmiProtocolDiscoveryCommon ( + IN SCMI_PROTOCOL_ID ProtocolId, + IN SCMI_MESSAGE_ID MessageId, + OUT UINT32 **ReturnValues + ) +{ + SCMI_COMMAND Command; + UINT32 PayloadLength = 0; + + Command.ProtocolId = ProtocolId; + Command.MessageId = MessageId; + + return ScmiCommandExecute ( + &Command, + &PayloadLength, + ReturnValues + ); +} + +/** Return protocol version from SCP for a given protocol ID. + + @param[in] Protocol ID Protocol ID. + @param[out] Version Pointer to version of the protocol. + + @retval EFI_SUCCESS Version holds a valid version received + from the SCP. + @retval EFI_DEVICE_ERROR SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +ScmiGetProtocolVersion ( + IN SCMI_PROTOCOL_ID ProtocolId, + OUT UINT32 *Version + ) +{ + EFI_STATUS Status; + UINT32 *ProtocolVersion; + + Status = ScmiProtocolDiscoveryCommon ( + ProtocolId, + SCMI_MESSAGE_ID_PROTOCOL_VERSION, + (UINT32**)&ProtocolVersion + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *Version = *ProtocolVersion; + + return EFI_SUCCESS; +} + +/** Return protocol attributes from SCP for a given protocol ID. + + @param[in] Protocol ID Protocol ID. + @param[out] ReturnValues Pointer to attributes of the protocol. + + @retval EFI_SUCCESS ReturnValues points to protocol attributes. + @retval EFI_DEVICE_ERROR SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +ScmiGetProtocolAttributes ( + IN SCMI_PROTOCOL_ID ProtocolId, + OUT UINT32 **ReturnValues + ) +{ + return ScmiProtocolDiscoveryCommon ( + ProtocolId, + SCMI_MESSAGE_ID_PROTOCOL_ATTRIBUTES, + ReturnValues + ); +} + +/** Return protocol message attributes from SCP for a given protocol ID. + + @param[in] Protocol ID Protocol ID. + @param[out] Attributes Pointer to attributes of the protocol. + + @retval EFI_SUCCESS ReturnValues points to protocol message attributes. + @retval EFI_DEVICE_ERROR SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +ScmiGetProtocolMessageAttributes ( + IN SCMI_PROTOCOL_ID ProtocolId, + OUT UINT32 **ReturnValues + ) +{ + return ScmiProtocolDiscoveryCommon ( + ProtocolId, + SCMI_MESSAGE_ID_PROTOCOL_MESSAGE_ATTRIBUTES, + ReturnValues + ); +} diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c new file mode 100644 index 0000000000..0829438c82 --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c @@ -0,0 +1,318 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#include +#include +#include +#include + +#include "ArmScmiBaseProtocolPrivate.h" +#include "ScmiPrivate.h" + +/** Return version of the Base protocol supported by SCP firmware. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] Version Version of the supported SCMI Base protocol. + + @retval EFI_SUCCESS The version of the protocol is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +BaseGetVersion ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT32 *Version + ) +{ + return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_BASE, Version); +} + +/** Return total number of SCMI protocols supported by the SCP firmware. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] TotalProtocols Total number of SCMI protocols supported. + + @retval EFI_SUCCESS Total number of protocols supported are returned. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +BaseGetTotalProtocols ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT32 *TotalProtocols + ) +{ + EFI_STATUS Status; + UINT32 *ReturnValues; + + Status = ScmiGetProtocolAttributes (SCMI_PROTOCOL_ID_BASE, &ReturnValues); + if (EFI_ERROR (Status)) { + return Status; + } + + *TotalProtocols = SCMI_TOTAL_PROTOCOLS (ReturnValues[0]); + + return EFI_SUCCESS; +} + +/** Common function which returns vendor details. + + @param[in] MessageId SCMI_MESSAGE_ID_BASE_DISCOVER_VENDOR + OR + SCMI_MESSAGE_ID_BASE_DISCOVER_SUB_VENDOR + + @param[out] VendorIdentifier ASCII name of the vendor/subvendor. + + @retval EFI_SUCCESS VendorIdentifier is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +BaseDiscoverVendorDetails ( + IN SCMI_MESSAGE_ID_BASE MessageId, + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] + ) +{ + EFI_STATUS Status; + UINT32 *ReturnValues; + SCMI_COMMAND Cmd; + UINT32 PayloadLength; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_BASE; + Cmd.MessageId = MessageId; + + PayloadLength = 0; + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + &ReturnValues + ); + if (EFI_ERROR (Status)) { + return Status; + } + + AsciiStrCpyS ( + (CHAR8*)VendorIdentifier, + SCMI_MAX_STR_LEN, + (CONST CHAR8*)ReturnValues + ); + + return EFI_SUCCESS; +} + +/** Return vendor name. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] VendorIdentifier Null terminated ASCII string of up to + 16 bytes with a vendor name. + + @retval EFI_SUCCESS VendorIdentifier is returned. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +BaseDiscoverVendor ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] + ) +{ + return BaseDiscoverVendorDetails ( + SCMI_MESSAGE_ID_BASE_DISCOVER_VENDOR, + VendorIdentifier + ); +} + +/** Return sub vendor name. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] VendorIdentifier Null terminated ASCII string of up to + 16 bytes with a sub vendor name. + + @retval EFI_SUCCESS VendorIdentifier is returned. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +BaseDiscoverSubVendor ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] + ) +{ + return BaseDiscoverVendorDetails ( + SCMI_MESSAGE_ID_BASE_DISCOVER_SUB_VENDOR, + VendorIdentifier + ); +} + +/** Return implementation version. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] ImplementationVersion Vendor specific implementation version. + + @retval EFI_SUCCESS Implementation version is returned. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +BaseDiscoverImplVersion ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT32 *ImplementationVersion + ) +{ + EFI_STATUS Status; + UINT32 *ReturnValues; + SCMI_COMMAND Cmd; + UINT32 PayloadLength; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_BASE; + Cmd.MessageId = SCMI_MESSAGE_ID_BASE_DISCOVER_IMPLEMENTATION_VERSION; + + PayloadLength = 0; + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + &ReturnValues + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *ImplementationVersion = ReturnValues[0]; + + return EFI_SUCCESS; +} + +/** Return list of protocols. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] ProtocolListSize Size of the ProtocolList. + + @param[out] ProtocolList Protocol list. + + @retval EFI_SUCCESS List of protocols is returned. + @retval EFI_BUFFER_TOO_SMALL ProtocolListSize is too small for the result. + It has been updated to the size needed. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +BaseDiscoverListProtocols ( + IN SCMI_BASE_PROTOCOL *This, + IN OUT UINT32 *ProtocolListSize, + OUT UINT8 *ProtocolList + ) +{ + EFI_STATUS Status; + UINT32 TotalProtocols; + UINT32 *MessageParams; + BASE_DISCOVER_LIST *DiscoverList; + UINT32 Skip; + UINT32 Index; + SCMI_COMMAND Cmd; + UINT32 PayloadLength; + UINT32 RequiredSize; + + Status = BaseGetTotalProtocols (This, &TotalProtocols); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + RequiredSize = sizeof (UINT8) * TotalProtocols; + if (*ProtocolListSize < RequiredSize) { + *ProtocolListSize = RequiredSize; + return EFI_BUFFER_TOO_SMALL; + } + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_BASE; + Cmd.MessageId = SCMI_MESSAGE_ID_BASE_DISCOVER_LIST_PROTOCOLS; + + Skip = 0; + + while (Skip < TotalProtocols) { + + *MessageParams = Skip; + + // Note PayloadLength is a IN/OUT parameter. + PayloadLength = sizeof (Skip); + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + (UINT32**)&DiscoverList + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < DiscoverList->NumProtocols; Index++) { + ProtocolList[Skip++] = DiscoverList->Protocols[Index]; + } + } + + *ProtocolListSize = RequiredSize; + + return EFI_SUCCESS; +} + +// Instance of the SCMI Base protocol. +STATIC CONST SCMI_BASE_PROTOCOL BaseProtocol = { + BaseGetVersion, + BaseGetTotalProtocols, + BaseDiscoverVendor, + BaseDiscoverSubVendor, + BaseDiscoverImplVersion, + BaseDiscoverListProtocols +}; + +/** Initialize Base protocol and install protocol on a given handle. + + @param[in] Handle Handle to install Base protocol. + + @retval EFI_SUCCESS Base protocol interface installed + successfully. +**/ +EFI_STATUS +ScmiBaseProtocolInit ( + IN OUT EFI_HANDLE* Handle + ) +{ + return gBS->InstallMultipleProtocolInterfaces ( + Handle, + &gArmScmiBaseProtocolGuid, + &BaseProtocol, + NULL + ); +} diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c new file mode 100644 index 0000000000..64d2afab72 --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c @@ -0,0 +1,418 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#include +#include +#include +#include + +#include "ArmScmiClockProtocolPrivate.h" +#include "ScmiPrivate.h" + +/** Convert to 64 bit value from two 32 bit words. + + @param[in] Low Lower 32 bits. + @param[in] High Higher 32 bits. + + @retval UINT64 64 bit value. +**/ +STATIC +UINT64 +ConvertTo64Bit ( + IN UINT32 Low, + IN UINT32 High + ) +{ + return (Low | ((UINT64)High << 32)); +} + +/** Return version of the clock management protocol supported by SCP firmware. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + + @param[out] Version Version of the supported SCMI Clock management protocol. + + @retval EFI_SUCCESS The version is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +ClockGetVersion ( + IN SCMI_CLOCK_PROTOCOL *This, + OUT UINT32 *Version + ) +{ + return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_CLOCK, Version); +} + +/** Return total number of clock devices supported by the clock management + protocol. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + + @param[out] TotalClocks Total number of clocks supported. + + @retval EFI_SUCCESS Total number of clocks supported is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +ClockGetTotalClocks ( + IN SCMI_CLOCK_PROTOCOL *This, + OUT UINT32 *TotalClocks + ) +{ + EFI_STATUS Status; + UINT32 *ReturnValues; + + Status = ScmiGetProtocolAttributes (SCMI_PROTOCOL_ID_CLOCK, &ReturnValues); + if (EFI_ERROR (Status)) { + return Status; + } + + *TotalClocks = SCMI_CLOCK_PROTOCOL_TOTAL_CLKS (ReturnValues[0]); + + return EFI_SUCCESS; +} + +/** Return attributes of a clock device. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + @param[in] ClockId Identifier for the clock device. + + @param[out] Enabled If TRUE, the clock device is enabled. + @param[out] ClockAsciiName A NULL terminated ASCII string with the clock + name, of up to 16 bytes. + + @retval EFI_SUCCESS Clock device attributes are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +ClockGetClockAttributes ( + IN SCMI_CLOCK_PROTOCOL *This, + IN UINT32 ClockId, + OUT BOOLEAN *Enabled, + OUT CHAR8 *ClockAsciiName + ) +{ + EFI_STATUS Status; + + UINT32 *MessageParams; + CLOCK_ATTRIBUTES *ClockAttributes; + SCMI_COMMAND Cmd; + UINT32 PayloadLength; + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + *MessageParams = ClockId; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK; + Cmd.MessageId = SCMI_MESSAGE_ID_CLOCK_ATTRIBUTES; + + PayloadLength = sizeof (ClockId); + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + (UINT32**)&ClockAttributes + ); + if (EFI_ERROR (Status)) { + return Status; + } + // TRUE if bit 0 of ClockAttributes->Attributes is set. + *Enabled = CLOCK_ENABLED (ClockAttributes->Attributes); + + AsciiStrCpyS ( + ClockAsciiName, + SCMI_MAX_STR_LEN, + (CONST CHAR8*)ClockAttributes->ClockName + ); + + return EFI_SUCCESS; +} + +/** Return list of rates supported by a given clock device. + + @param[in] This A pointer to SCMI_CLOCK_PROTOCOL Instance. + @param[in] ClockId Identifier for the clock device. + + @param[out] Format SCMI_CLOCK_RATE_FORMAT_DISCRETE: Clock device + supports range of clock rates which are non-linear. + + SCMI_CLOCK_RATE_FORMAT_LINEAR: Clock device supports + range of linear clock rates from Min to Max in steps. + + @param[out] TotalRates Total number of rates. + + @param[in,out] RateArraySize Size of the RateArray. + + @param[out] RateArray List of clock rates. + + @retval EFI_SUCCESS List of clock rates is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval EFI_BUFFER_TOO_SMALL RateArraySize is too small for the result. + It has been updated to the size needed. + @retval !(EFI_SUCCESS) Other errors. +**/ +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 + ) +{ + EFI_STATUS Status; + + UINT32 PayloadLength; + SCMI_COMMAND Cmd; + UINT32 *MessageParams; + CLOCK_DESCRIBE_RATES *DescribeRates; + CLOCK_RATE_DWORD *Rate; + + UINT32 RequiredArraySize = 0; + UINT32 RateIndex = 0; + UINT32 RateNo; + UINT32 RateOffset; + + *TotalRates = 0; + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK; + Cmd.MessageId = SCMI_MESSAGE_ID_CLOCK_DESCRIBE_RATES; + + *MessageParams++ = ClockId; + + do { + + *MessageParams = RateIndex; + + // Set Payload length, note PayloadLength is a IN/OUT parameter. + PayloadLength = sizeof (ClockId) + sizeof (RateIndex); + + // Execute and wait for response on a SCMI channel. + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + (UINT32**)&DescribeRates + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (*TotalRates == 0) { + // In the first iteration we will get number of returned rates and number + // of remaining rates. With this information calculate required size + // for rate array. If provided RateArraySize is less, return an + // error. + + *Format = RATE_FORMAT (DescribeRates->NumRatesFlags); + + *TotalRates = NUM_RATES (DescribeRates->NumRatesFlags) + + NUM_REMAIN_RATES (DescribeRates->NumRatesFlags); + + if (*Format == SCMI_CLOCK_RATE_FORMAT_DISCRETE) { + RequiredArraySize = (*TotalRates) * sizeof (UINT64); + } else { + // We need to return triplet of 64 bit value for each rate + RequiredArraySize = (*TotalRates) * 3 * sizeof (UINT64); + } + + if (RequiredArraySize > (*RateArraySize)) { + *RateArraySize = RequiredArraySize; + return EFI_BUFFER_TOO_SMALL; + } + } + + RateOffset = 0; + + if (*Format == SCMI_CLOCK_RATE_FORMAT_DISCRETE) { + for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) { + Rate = &DescribeRates->Rates[RateOffset++]; + // Non-linear discrete rates. + RateArray[RateIndex++].Rate = ConvertTo64Bit (Rate->Low, Rate->High); + } + } else { + for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) { + // Linear clock rates from minimum to maximum in steps + // Minimum clock rate. + Rate = &DescribeRates->Rates[RateOffset++]; + RateArray[RateIndex].Min = ConvertTo64Bit (Rate->Low, Rate->High); + + Rate = &DescribeRates->Rates[RateOffset++]; + // Maximum clock rate. + RateArray[RateIndex].Max = ConvertTo64Bit (Rate->Low, Rate->High); + + Rate = &DescribeRates->Rates[RateOffset++]; + // Step. + RateArray[RateIndex++].Step = ConvertTo64Bit (Rate->Low, Rate->High); + } + } + } while (NUM_REMAIN_RATES (DescribeRates->NumRatesFlags) != 0); + + // Update RateArraySize with RequiredArraySize. + *RateArraySize = RequiredArraySize; + + return EFI_SUCCESS; +} + +/** Get clock rate. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + @param[in] ClockId Identifier for the clock device. + + @param[out] Rate Clock rate. + + @retval EFI_SUCCESS Clock rate is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +ClockRateGet ( + IN SCMI_CLOCK_PROTOCOL *This, + IN UINT32 ClockId, + OUT UINT64 *Rate + ) +{ + EFI_STATUS Status; + + UINT32 *MessageParams; + CLOCK_RATE_DWORD *ClockRate; + SCMI_COMMAND Cmd; + + UINT32 PayloadLength; + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + // Fill arguments for clock protocol command. + *MessageParams = ClockId; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK; + Cmd.MessageId = SCMI_MESSAGE_ID_CLOCK_RATE_GET; + + PayloadLength = sizeof (ClockId); + + // Execute and wait for response on a SCMI channel. + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + (UINT32**)&ClockRate + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *Rate = ConvertTo64Bit (ClockRate->Low, ClockRate->High); + + return EFI_SUCCESS; +} + +/** Set clock rate. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + @param[in] ClockId Identifier for the clock device. + @param[in] Rate Clock rate. + + @retval EFI_SUCCESS Clock rate set success. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +ClockRateSet ( + IN SCMI_CLOCK_PROTOCOL *This, + IN UINT32 ClockId, + IN UINT64 Rate + ) +{ + EFI_STATUS Status; + CLOCK_RATE_SET_ATTRIBUTES *ClockRateSetAttributes; + SCMI_COMMAND Cmd; + UINT32 PayloadLength; + + Status = ScmiCommandGetPayload ((UINT32**)&ClockRateSetAttributes); + if (EFI_ERROR (Status)) { + return Status; + } + + // Fill arguments for clock protocol command. + ClockRateSetAttributes->ClockId = ClockId; + ClockRateSetAttributes->Flags = CLOCK_SET_DEFAULT_FLAGS; + ClockRateSetAttributes->Rate.Low = (UINT32)Rate; + ClockRateSetAttributes->Rate.High = (UINT32)(Rate >> 32); + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK; + Cmd.MessageId = SCMI_MESSAGE_ID_CLOCK_RATE_SET; + + PayloadLength = sizeof (CLOCK_RATE_SET_ATTRIBUTES); + + // Execute and wait for response on a SCMI channel. + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + NULL + ); + + return Status; +} + +// Instance of the SCMI clock management protocol. +STATIC CONST SCMI_CLOCK_PROTOCOL ScmiClockProtocol = { + ClockGetVersion, + ClockGetTotalClocks, + ClockGetClockAttributes, + ClockDescribeRates, + ClockRateGet, + ClockRateSet + }; + +/** Initialize clock management protocol and install protocol on a given handle. + + @param[in] Handle Handle to install clock management protocol. + + @retval EFI_SUCCESS Clock protocol interface installed successfully. +**/ +EFI_STATUS +ScmiClockProtocolInit ( + IN EFI_HANDLE* Handle + ) +{ + return gBS->InstallMultipleProtocolInterfaces ( + Handle, + &gArmScmiClockProtocolGuid, + &ScmiClockProtocol, + NULL + ); +} diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c new file mode 100644 index 0000000000..2920c6f6f3 --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c @@ -0,0 +1,138 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include "ArmScmiBaseProtocolPrivate.h" +#include "ArmScmiClockProtocolPrivate.h" +#include "ArmScmiPerformanceProtocolPrivate.h" +#include "ScmiDxe.h" +#include "ScmiPrivate.h" + +STATIC CONST SCMI_PROTOCOL_INIT_TABLE ProtocolInitFxns[MAX_PROTOCOLS] = { + { ScmiBaseProtocolInit }, + { NULL }, + { NULL }, + { ScmiPerformanceProtocolInit }, + { ScmiClockProtocolInit }, + { NULL } +}; + +/** ARM SCMI driver entry point function. + + This function installs the SCMI Base protocol and a list of other + protocols is queried using the Base protocol. If protocol is supported, + driver will call each protocol init function to install the protocol on + the ImageHandle. + + @param[in] ImageHandle Handle to this EFI Image which will be used to + install Base, Clock and Performance protocols. + @param[in] SystemTable A pointer to boot time system table. + + @retval EFI_SUCCESS Driver initalized successfully. + @retval EFI_UNSUPPORTED If SCMI base protocol version is not supported. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +EFIAPI +ArmScmiDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SCMI_BASE_PROTOCOL *BaseProtocol; + UINT32 Version; + UINT32 Index; + UINT32 NumProtocols; + UINT32 ProtocolNo; + UINT8 SupportedList[MAX_PROTOCOLS]; + UINT32 SupportedListSize = sizeof (SupportedList); + + ProtocolNo = SCMI_PROTOCOL_ID_BASE & PROTOCOL_ID_MASK; + + // Every SCMI implementation must implement the base protocol. + Status = ProtocolInitFxns[ProtocolNo].Init (&ImageHandle); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + + Status = gBS->LocateProtocol ( + &gArmScmiBaseProtocolGuid, + NULL, + (VOID**)&BaseProtocol + ); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + + // Get SCMI Base protocol version. + Status = BaseProtocol->GetVersion (BaseProtocol, &Version); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + + if (Version != BASE_PROTOCOL_VERSION) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + // Apart from Base protocol, SCMI may implement various other protocols, + // query total protocols implemented by the SCP firmware. + NumProtocols = 0; + Status = BaseProtocol->GetTotalProtocols (BaseProtocol, &NumProtocols); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + + ASSERT (NumProtocols != 0); + + // Get the list of protocols supported by SCP firmware on the platform. + Status = BaseProtocol->DiscoverListProtocols ( + BaseProtocol, + &SupportedListSize, + SupportedList + ); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + + // Install supported protocol on ImageHandle. + for (Index = 0; Index < NumProtocols; Index++) { + ProtocolNo = SupportedList[Index] & PROTOCOL_ID_MASK; + if (ProtocolInitFxns[ProtocolNo].Init != NULL) { + Status = ProtocolInitFxns[ProtocolNo].Init (&ImageHandle); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return Status; + } + } + } + + return EFI_SUCCESS; +} diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h b/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h new file mode 100644 index 0000000000..29cdde1736 --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h @@ -0,0 +1,41 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ +#ifndef SCMI_DXE_H_ +#define SCMI_DXE_H_ + +#define MAX_PROTOCOLS 6 +#define PROTOCOL_ID_MASK 0xF +#define MAX_VENDOR_LEN SCMI_MAX_STR_LEN + +/** Pointer to protocol initialization function. + + @param[in] Handle A pointer to the EFI_HANDLE on which the protocol + interface is to be installed. + + @retval EFI_SUCCESS Protocol interface installed successfully. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_PROTOCOL_INIT_FXN)( + IN EFI_HANDLE *Handle + ); + +typedef struct { + SCMI_PROTOCOL_INIT_FXN Init; +} SCMI_PROTOCOL_INIT_TABLE; + +#endif /* SCMI_DXE_H_ */ diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c new file mode 100644 index 0000000000..e012424a9b --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c @@ -0,0 +1,457 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#include +#include +#include + +#include "ArmScmiPerformanceProtocolPrivate.h" +#include "ScmiPrivate.h" + +/** Return version of the performance management protocol supported by SCP. + firmware. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + + @param[out] Version Version of the supported SCMI performance management + protocol. + + @retval EFI_SUCCESS The version is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +PerformanceGetVersion ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + OUT UINT32 *Version + ) +{ + return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_PERFORMANCE, Version); +} + +/** Return protocol attributes of the performance management protocol. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + + @param[out] Attributes Protocol attributes. + + @retval EFI_SUCCESS Protocol attributes are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +PerformanceGetAttributes ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES *Attributes + ) +{ + EFI_STATUS Status; + UINT32* ReturnValues; + + Status = ScmiGetProtocolAttributes ( + SCMI_PROTOCOL_ID_PERFORMANCE, + &ReturnValues + ); + if (EFI_ERROR (Status)) { + return Status; + } + + CopyMem ( + Attributes, + ReturnValues, + sizeof (SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES) + ); + + return EFI_SUCCESS; +} + +/** Return performance domain attributes. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + + @param[out] Attributes Performance domain attributes. + + @retval EFI_SUCCESS Domain attributes are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +PerformanceDomainAttributes ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES *DomainAttributes + ) +{ + EFI_STATUS Status; + UINT32 *MessageParams; + UINT32 *ReturnValues; + UINT32 PayloadLength; + SCMI_COMMAND Cmd; + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + *MessageParams = DomainId; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_DOMAIN_ATTRIBUTES; + + PayloadLength = sizeof (DomainId); + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + &ReturnValues + ); + if (EFI_ERROR (Status)) { + return Status; + } + + CopyMem ( + DomainAttributes, + ReturnValues, + sizeof (SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES) + ); + + return EFI_SUCCESS; +} + +/** Return list of performance domain levels of a given domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + + @param[out] NumLevels Total number of levels a domain can support. + + @param[in,out] LevelArraySize Size of the performance level array. + + @param[out] LevelArray Array of the performance levels. + + @retval EFI_SUCCESS Domain levels are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result. + It has been updated to the size needed. + @retval !(EFI_SUCCESS) Other errors. +**/ +STATIC +EFI_STATUS +PerformanceDescribeLevels ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + OUT UINT32 *NumLevels, + IN OUT UINT32 *LevelArraySize, + OUT SCMI_PERFORMANCE_LEVEL *LevelArray + ) +{ + EFI_STATUS Status; + UINT32 PayloadLength; + SCMI_COMMAND Cmd; + UINT32* MessageParams; + UINT32 LevelIndex; + UINT32 RequiredSize; + UINT32 LevelNo; + UINT32 ReturnNumLevels; + UINT32 ReturnRemainNumLevels; + + PERF_DESCRIBE_LEVELS *Levels; + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + LevelIndex = 0; + RequiredSize = 0; + + *MessageParams++ = DomainId; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS; + + do { + + *MessageParams = LevelIndex; + + // Note, PayloadLength is an IN/OUT parameter. + PayloadLength = sizeof (DomainId) + sizeof (LevelIndex); + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + (UINT32**)&Levels + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ReturnNumLevels = NUM_PERF_LEVELS (Levels->NumLevels); + ReturnRemainNumLevels = NUM_REMAIN_PERF_LEVELS (Levels->NumLevels); + + if (RequiredSize == 0) { + *NumLevels = ReturnNumLevels + ReturnRemainNumLevels; + + RequiredSize = (*NumLevels) * sizeof (SCMI_PERFORMANCE_LEVEL); + if (RequiredSize > (*LevelArraySize)) { + // Update LevelArraySize with required size. + *LevelArraySize = RequiredSize; + return EFI_BUFFER_TOO_SMALL; + } + } + + for (LevelNo = 0; LevelNo < ReturnNumLevels; LevelNo++) { + CopyMem ( + &LevelArray[LevelIndex++], + &Levels->PerfLevel[LevelNo], + sizeof (SCMI_PERFORMANCE_LEVEL) + ); + } + + } while (ReturnRemainNumLevels != 0); + + *LevelArraySize = RequiredSize; + + return EFI_SUCCESS; +} + +/** Set performance limits of a domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + @param[in] Limit Performance limit to set. + + @retval EFI_SUCCESS Performance limits set successfully. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +PerformanceLimitsSet ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + IN SCMI_PERFORMANCE_LIMITS *Limits + ) +{ + EFI_STATUS Status; + UINT32 PayloadLength; + SCMI_COMMAND Cmd; + UINT32 *MessageParams; + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + *MessageParams++ = DomainId; + *MessageParams++ = Limits->RangeMax; + *MessageParams = Limits->RangeMin; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET; + + PayloadLength = sizeof (DomainId) + sizeof (SCMI_PERFORMANCE_LIMITS); + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + NULL + ); + + return Status; +} + +/** Get performance limits of a domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + + @param[out] Limit Performance Limits of the domain. + + @retval EFI_SUCCESS Performance limits are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +PerformanceLimitsGet ( + SCMI_PERFORMANCE_PROTOCOL *This, + UINT32 DomainId, + SCMI_PERFORMANCE_LIMITS *Limits + ) +{ + EFI_STATUS Status; + UINT32 PayloadLength; + SCMI_COMMAND Cmd; + UINT32 *MessageParams; + + SCMI_PERFORMANCE_LIMITS *ReturnValues; + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + *MessageParams = DomainId; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET; + + PayloadLength = sizeof (DomainId); + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + (UINT32**)&ReturnValues + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Limits->RangeMax = ReturnValues->RangeMax; + Limits->RangeMin = ReturnValues->RangeMin; + + return EFI_SUCCESS; +} + +/** Set performance level of a domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + @param[in] Level Performance level of the domain. + + @retval EFI_SUCCESS Performance level set successfully. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +PerformanceLevelSet ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + IN UINT32 Level + ) +{ + EFI_STATUS Status; + UINT32 PayloadLength; + SCMI_COMMAND Cmd; + UINT32 *MessageParams; + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + *MessageParams++ = DomainId; + *MessageParams = Level; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET; + + PayloadLength = sizeof (DomainId) + sizeof (Level); + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + NULL + ); + + return Status; +} + +/** Get performance level of a domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + + @param[out] Level Performance level of the domain. + + @retval EFI_SUCCESS Performance level got successfully. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +PerformanceLevelGet ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + OUT UINT32 *Level + ) +{ + EFI_STATUS Status; + UINT32 PayloadLength; + SCMI_COMMAND Cmd; + UINT32 *ReturnValues; + UINT32 *MessageParams; + + Status = ScmiCommandGetPayload (&MessageParams); + if (EFI_ERROR (Status)) { + return Status; + } + + *MessageParams = DomainId; + + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET; + + PayloadLength = sizeof (DomainId); + + Status = ScmiCommandExecute ( + &Cmd, + &PayloadLength, + &ReturnValues + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *Level = *ReturnValues; + + return EFI_SUCCESS; +} + +// Instance of the SCMI performance management protocol. +STATIC CONST SCMI_PERFORMANCE_PROTOCOL PerformanceProtocol = { + PerformanceGetVersion, + PerformanceGetAttributes, + PerformanceDomainAttributes, + PerformanceDescribeLevels, + PerformanceLimitsSet, + PerformanceLimitsGet, + PerformanceLevelSet, + PerformanceLevelGet +}; + +/** Initialize performance management protocol and install on a given Handle. + + @param[in] Handle Handle to install performance management + protocol. + + @retval EFI_SUCCESS Performance protocol installed successfully. +**/ +EFI_STATUS +ScmiPerformanceProtocolInit ( + IN EFI_HANDLE* Handle + ) +{ + return gBS->InstallMultipleProtocolInterfaces ( + Handle, + &gArmScmiPerformanceProtocolGuid, + &PerformanceProtocol, + NULL + ); +} diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h b/ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h new file mode 100644 index 0000000000..df03655b8b --- /dev/null +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h @@ -0,0 +1,174 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ +#ifndef SCMI_PRIVATE_H_ +#define SCMI_PRIVATE_H_ + +// SCMI protocol IDs. +typedef enum { + SCMI_PROTOCOL_ID_BASE = 0x10, + SCMI_PROTOCOL_ID_POWER_DOMAIN = 0x11, + SCMI_PROTOCOL_ID_SYSTEM_POWER = 0x12, + SCMI_PROTOCOL_ID_PERFORMANCE = 0x13, + SCMI_PROTOCOL_ID_CLOCK = 0x14, + SCMI_PROTOCOL_ID_SENSOR = 0x15 +} SCMI_PROTOCOL_ID; + +// SCMI message types. +typedef enum { + SCMI_MESSAGE_TYPE_COMMAND = 0, + SCMI_MESSAGE_TYPE_DELAYED_RESPONSE = 2, // Skipping 1 is deliberate. + SCMI_MESSAGE_TYPE_NOTIFICATION = 3 +} SCMI_MESSAGE_TYPE; + +// SCMI response error codes. +typedef enum { + SCMI_SUCCESS = 0, + SCMI_NOT_SUPPORTED = -1, + SCMI_INVALID_PARAMETERS = -2, + SCMI_DENIED = -3, + SCMI_NOT_FOUND = -4, + SCMI_OUT_OF_RANGE = -5, + SCMI_BUSY = -6, + SCMI_COMMS_ERROR = -7, + SCMI_GENERIC_ERROR = -8, + SCMI_HARDWARE_ERROR = -9, + SCMI_PROTOCOL_ERROR = -10 +} SCMI_STATUS; + +// SCMI message IDs common to all protocols. +typedef enum { + SCMI_MESSAGE_ID_PROTOCOL_VERSION = 0x0, + SCMI_MESSAGE_ID_PROTOCOL_ATTRIBUTES = 0x1, + SCMI_MESSAGE_ID_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2 +} SCMI_MESSAGE_ID; + +// Not defined in SCMI specification but will help to identify a message. +typedef struct { + SCMI_PROTOCOL_ID ProtocolId; + UINT32 MessageId; +} SCMI_COMMAND; + +#pragma pack(1) + +// Response to a SCMI command. +typedef struct { + INT32 Status; + UINT32 ReturnValues[]; +} SCMI_MESSAGE_RESPONSE; + +// Message header. MsgId[7:0], MsgType[9:8], ProtocolId[17:10] +#define MESSAGE_TYPE_SHIFT 8 +#define PROTOCOL_ID_SHIFT 10 +#define SCMI_MESSAGE_HEADER(MsgId, MsgType, ProtocolId) ( \ + MsgType << MESSAGE_TYPE_SHIFT | \ + ProtocolId << PROTOCOL_ID_SHIFT | \ + MsgId \ + ) +// SCMI message header. +typedef struct { + UINT32 MessageHeader; +} SCMI_MESSAGE_HEADER; + +#pragma pack() + +/** Return a pointer to the message payload. + + @param[out] Payload Holds pointer to the message payload. + + @retval EFI_SUCCESS Payload holds a valid message payload pointer. + @retval EFI_TIMEOUT Time out error if MTL channel is busy. + @retval EFI_UNSUPPORTED If MTL channel is unsupported. +**/ +EFI_STATUS +ScmiCommandGetPayload ( + OUT UINT32** Payload + ); + +/** Execute a SCMI command and receive a response. + + This function uses a MTL channel to transfer message to SCP + and waits for a response. + + @param[in] Command Pointer to the SCMI command (Protocol ID + and Message ID) + + @param[in,out] PayloadLength SCMI command message length. + + @param[out] OPTIONAL ReturnValues Pointer to SCMI response. + + @retval OUT EFI_SUCCESS Command sent and message received successfully. + @retval OUT EFI_UNSUPPORTED Channel not supported. + @retval OUT EFI_TIMEOUT Timeout on the channel. + @retval OUT EFI_DEVICE_ERROR Channel not ready. + @retval OUT EFI_DEVICE_ERROR Message Header corrupted. + @retval OUT EFI_DEVICE_ERROR SCMI error. +**/ +EFI_STATUS +ScmiCommandExecute ( + IN SCMI_COMMAND *Command, + IN OUT UINT32 *PayloadLength, + OUT UINT32 **ReturnValues OPTIONAL + ); + +/** Return protocol version from SCP for a given protocol ID. + + @param[in] Protocol ID Protocol ID. + @param[out] Version Pointer to version of the protocol. + + @retval EFI_SUCCESS Version holds a valid version received + from the SCP. + @retval EFI_DEVICE_ERROR SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +ScmiGetProtocolVersion ( + IN SCMI_PROTOCOL_ID ProtocolId, + OUT UINT32 *Version + ); + +/** Return protocol attributes from SCP for a given protocol ID. + + @param[in] Protocol ID Protocol ID. + @param[out] ReturnValues Pointer to attributes of the protocol. + + @retval EFI_SUCCESS ReturnValues points to protocol attributes. + @retval EFI_DEVICE_ERROR SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +ScmiGetProtocolAttributes ( + IN SCMI_PROTOCOL_ID ProtocolId, + OUT UINT32 **ReturnValues + ); + +/** Return protocol message attributes from SCP for a given protocol ID. + + @param[in] Protocol ID Protocol ID. + + @param[out] Attributes Pointer to attributes of the protocol. + + @retval EFI_SUCCESS ReturnValues points to protocol message attributes. + @retval EFI_DEVICE_ERROR SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +EFI_STATUS +ScmiGetProtocolMessageAttributes ( + IN SCMI_PROTOCOL_ID ProtocolId, + OUT UINT32 **ReturnValues + ); + +#endif /* SCMI_PRIVATE_H_ */ diff --git a/ArmPkg/Include/Protocol/ArmScmi.h b/ArmPkg/Include/Protocol/ArmScmi.h new file mode 100644 index 0000000000..239abb9706 --- /dev/null +++ b/ArmPkg/Include/Protocol/ArmScmi.h @@ -0,0 +1,27 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#ifndef ARM_SCMI_H_ +#define ARM_SCMI_H_ + +/* As per SCMI specification, maximum allowed ASCII string length + for various return values/parameters of a SCMI message. +*/ +#define SCMI_MAX_STR_LEN 16 + +#endif /* ARM_SCMI_H_ */ + diff --git a/ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h b/ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h new file mode 100644 index 0000000000..ecc41f2181 --- /dev/null +++ b/ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h @@ -0,0 +1,174 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#ifndef ARM_SCMI_BASE_PROTOCOL_H_ +#define ARM_SCMI_BASE_PROTOCOL_H_ + +#include + +#define BASE_PROTOCOL_VERSION 0x10000 + +#define NUM_PROTOCOL_MASK 0xFFU +#define NUM_AGENT_MASK 0xFFU + +#define NUM_AGENT_SHIFT 0x8 + +/** Returns total number of protocols that are + implemented (excluding the Base protocol) +*/ +#define SCMI_TOTAL_PROTOCOLS(Attr) (Attr & NUM_PROTOCOL_MASK) + +// Returns total number of agents in the system. +#define SCMI_TOTAL_AGENTS(Attr) ((Attr >> NUM_AGENT_SHIFT) & NUM_AGENT_MASK) + +#define ARM_SCMI_BASE_PROTOCOL_GUID { \ + 0xd7e5abe9, 0x33ab, 0x418e, {0x9f, 0x91, 0x72, 0xda, 0xe2, 0xba, 0x8e, 0x2f} \ + } + +extern EFI_GUID gArmScmiBaseProtocolGuid; + +typedef struct _SCMI_BASE_PROTOCOL SCMI_BASE_PROTOCOL; + +/** Return version of the Base protocol supported by SCP firmware. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] Version Version of the supported SCMI Base protocol. + + @retval EFI_SUCCESS The version of the protocol is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_BASE_GET_VERSION) ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT32 *Version + ); + +/** Return total number of SCMI protocols supported by the SCP firmware. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] TotalProtocols Total number of SCMI protocols supported. + + @retval EFI_SUCCESS Total number of protocols supported are returned. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_BASE_GET_TOTAL_PROTOCOLS) ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT32 *TotalProtocols + ); + +/** Return vendor name. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] VendorIdentifier Null terminated ASCII string of up to + 16 bytes with a vendor name. + + @retval EFI_SUCCESS VendorIdentifier is returned. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_BASE_DISCOVER_VENDOR) ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] + ); + +/** Return sub vendor name. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] VendorIdentifier Null terminated ASCII string of up to + 16 bytes with a vendor name. + + @retval EFI_SUCCESS VendorIdentifier is returned. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_BASE_DISCOVER_SUB_VENDOR) ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] + ); + +/** Return implementation version. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] ImplementationVersion Vendor specific implementation version. + + @retval EFI_SUCCESS Implementation version is returned. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION) ( + IN SCMI_BASE_PROTOCOL *This, + OUT UINT32 *ImplementationVersion + ); + +/** Return list of protocols. + + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. + + @param[out] ProtocolListSize Size of the ProtocolList. + + @param[out] ProtocolList Protocol list. + + @retval EFI_SUCCESS List of protocols is returned. + @retval EFI_BUFFER_TOO_SMALL ProtocolListSize is too small for the result. + It has been updated to the size needed. + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_BASE_DISCOVER_LIST_PROTOCOLS) ( + IN SCMI_BASE_PROTOCOL *This, + IN OUT UINT32 *ProtocolListSize, + OUT UINT8 *ProtocolList + ); + +// Base protocol. +typedef struct _SCMI_BASE_PROTOCOL { + SCMI_BASE_GET_VERSION GetVersion; + SCMI_BASE_GET_TOTAL_PROTOCOLS GetTotalProtocols; + SCMI_BASE_DISCOVER_VENDOR DiscoverVendor; + SCMI_BASE_DISCOVER_SUB_VENDOR DiscoverSubVendor; + SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION DiscoverImplementationVersion; + SCMI_BASE_DISCOVER_LIST_PROTOCOLS DiscoverListProtocols; +} SCMI_BASE_PROTOCOL; + +// SCMI Message IDs for Base protocol. +typedef enum { + SCMI_MESSAGE_ID_BASE_DISCOVER_VENDOR = 0x3, + SCMI_MESSAGE_ID_BASE_DISCOVER_SUB_VENDOR = 0x4, + SCMI_MESSAGE_ID_BASE_DISCOVER_IMPLEMENTATION_VERSION = 0x5, + SCMI_MESSAGE_ID_BASE_DISCOVER_LIST_PROTOCOLS = 0x6 +} SCMI_MESSAGE_ID_BASE; + +#endif /* ARM_SCMI_BASE_PROTOCOL_H_ */ + diff --git a/ArmPkg/Include/Protocol/ArmScmiClockProtocol.h b/ArmPkg/Include/Protocol/ArmScmiClockProtocol.h new file mode 100644 index 0000000000..3db26cb064 --- /dev/null +++ b/ArmPkg/Include/Protocol/ArmScmiClockProtocol.h @@ -0,0 +1,218 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#ifndef ARM_SCMI_CLOCK_PROTOCOL_H_ +#define ARM_SCMI_CLOCK_PROTOCOL_H_ + +#include + +#define ARM_SCMI_CLOCK_PROTOCOL_GUID { \ + 0x91ce67a8, 0xe0aa, 0x4012, {0xb9, 0x9f, 0xb6, 0xfc, 0xf3, 0x4, 0x8e, 0xaa} \ + } + +extern EFI_GUID gArmScmiClockProtocolGuid; + +// Message Type for clock management protocol. +typedef enum { + SCMI_MESSAGE_ID_CLOCK_ATTRIBUTES = 0x3, + SCMI_MESSAGE_ID_CLOCK_DESCRIBE_RATES = 0x4, + SCMI_MESSAGE_ID_CLOCK_RATE_SET = 0x5, + SCMI_MESSAGE_ID_CLOCK_RATE_GET = 0x6, + SCMI_MESSAGE_ID_CLOCK_CONFIG_SET = 0x7 +} SCMI_MESSAGE_ID_CLOCK; + +typedef enum { + SCMI_CLOCK_RATE_FORMAT_DISCRETE, // Non-linear range. + SCMI_CLOCK_RATE_FORMAT_LINEAR // Linear range. +} SCMI_CLOCK_RATE_FORMAT; + +// Clock management protocol version. +#define SCMI_CLOCK_PROTOCOL_VERSION 0x10000 + +#define SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_MASK 0xFFU +#define SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_SHIFT 16 +#define SCMI_CLOCK_PROTOCOL_NUM_CLOCKS_MASK 0xFFFFU + +/** Total number of pending asynchronous clock rates changes + supported by the SCP, Attr Bits[23:16] +*/ +#define SCMI_CLOCK_PROTOCOL_MAX_ASYNC_CLK_RATES(Attr) ( \ + (Attr >> SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_SHIFT) && \ + SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_MASK) + +// Total of clock devices supported by the SCP, Attr Bits[15:0] +#define SCMI_CLOCK_PROTOCOL_TOTAL_CLKS(Attr) (Attr & SCMI_CLOCK_PROTOCOL_NUM_CLOCKS_MASK) + +#pragma pack(1) + +/* Depending on the format (linear/non-linear) supported by a clock device + either Rate or Min/Max/Step triplet is valid. +*/ +typedef struct { + union { + UINT64 Min; + UINT64 Rate; + }; + UINT64 Max; + UINT64 Step; +} SCMI_CLOCK_RATE; + +#pragma pack() + +typedef struct _SCMI_CLOCK_PROTOCOL SCMI_CLOCK_PROTOCOL; + +// Protocol Interface functions. + +/** Return version of the clock management protocol supported by SCP firmware. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + + @param[out] Version Version of the supported SCMI Clock management protocol. + + @retval EFI_SUCCESS The version is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_CLOCK_GET_VERSION) ( + IN SCMI_CLOCK_PROTOCOL *This, + OUT UINT32 *Version + ); + +/** Return total number of clock devices supported by the clock management + protocol. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + + @param[out] TotalClocks Total number of clocks supported. + + @retval EFI_SUCCESS Total number of clocks supported is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_CLOCK_GET_TOTAL_CLOCKS) ( + IN SCMI_CLOCK_PROTOCOL *This, + OUT UINT32 *TotalClocks + ); + +/** Return attributes of a clock device. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + @param[in] ClockId Identifier for the clock device. + + @param[out] Enabled If TRUE, the clock device is enabled. + @param[out] ClockAsciiName A NULL terminated ASCII string with the clock + name, of up to 16 bytes. + + @retval EFI_SUCCESS Clock device attributes are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_CLOCK_GET_CLOCK_ATTRIBUTES) ( + IN SCMI_CLOCK_PROTOCOL *This, + IN UINT32 ClockId, + OUT BOOLEAN *Enabled, + OUT CHAR8 *ClockAsciiName + ); + +/** Return list of rates supported by a given clock device. + + @param[in] This A pointer to SCMI_CLOCK_PROTOCOL Instance. + @param[in] ClockId Identifier for the clock device. + + @param[out] Format SCMI_CLOCK_RATE_FORMAT_DISCRETE: Clock device + supports range of clock rates which are non-linear. + + SCMI_CLOCK_RATE_FORMAT_LINEAR: Clock device supports + range of linear clock rates from Min to Max in steps. + + @param[out] TotalRates Total number of rates. + + @param[in,out] RateArraySize Size of the RateArray. + + @param[out] RateArray List of clock rates. + + @retval EFI_SUCCESS List of clock rates are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval EFI_BUFFER_TOO_SMALL RateArraySize is too small for the result. + It has been updated to the size needed. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_CLOCK_DESCRIBE_RATES) ( + 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 + ); + +/** Get clock rate. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + @param[in] ClockId Identifier for the clock device. + + @param[out] Rate Clock rate. + + @retval EFI_SUCCESS Clock rate is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_CLOCK_RATE_GET) ( + IN SCMI_CLOCK_PROTOCOL *This, + IN UINT32 ClockId, + OUT UINT64 *Rate + ); + +/** Set clock rate. + + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. + @param[in] ClockId Identifier for the clock device. + @param[in] Rate Clock rate. + + @retval EFI_SUCCESS Clock rate set success. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_CLOCK_RATE_SET) ( + IN SCMI_CLOCK_PROTOCOL *This, + IN UINT32 ClockId, + IN UINT64 Rate + ); + +typedef struct _SCMI_CLOCK_PROTOCOL { + SCMI_CLOCK_GET_VERSION GetVersion; + SCMI_CLOCK_GET_TOTAL_CLOCKS GetTotalClocks; + SCMI_CLOCK_GET_CLOCK_ATTRIBUTES GetClockAttributes; + SCMI_CLOCK_DESCRIBE_RATES DescribeRates; + SCMI_CLOCK_RATE_GET RateGet; + SCMI_CLOCK_RATE_SET RateSet; +} SCMI_CLOCK_PROTOCOL; + +#endif /* ARM_SCMI_CLOCK_PROTOCOL_H_ */ + diff --git a/ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h b/ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h new file mode 100644 index 0000000000..1d1af6f8be --- /dev/null +++ b/ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h @@ -0,0 +1,265 @@ +/** @file + + Copyright (c) 2017-2018, Arm Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + System Control and Management Interface V1.0 + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ + DEN0056A_System_Control_and_Management_Interface.pdf +**/ + +#ifndef ARM_SCMI_PERFORMANCE_PROTOCOL_H_ +#define ARM_SCMI_PERFORMANCE_PROTOCOL_H_ + +#include + +#define PERFORMANCE_PROTOCOL_VERSION 0x10000 + +#define ARM_SCMI_PERFORMANCE_PROTOCOL_GUID { \ + 0x9b8ba84, 0x3dd3, 0x49a6, {0xa0, 0x5a, 0x31, 0x34, 0xa5, 0xf0, 0x7b, 0xad} \ + } + +extern EFI_GUID gArmScmiPerformanceProtocolGuid; + +typedef struct _SCMI_PERFORMANCE_PROTOCOL SCMI_PERFORMANCE_PROTOCOL; + +#pragma pack(1) + +#define POWER_IN_MW_SHIFT 16 +#define POWER_IN_MW_MASK 0x1 +#define NUM_PERF_DOMAINS_MASK 0xFFFF + +// Total number of performance domains, Attr Bits [15:0] +#define SCMI_PERF_TOTAL_DOMAINS(Attr) (Attr & NUM_PERF_DOMAINS_MASK) + +// A flag to express power values in mW or platform specific way, Attr Bit [16] +#define SCMI_PERF_POWER_IN_MW(Attr) ((Attr >> POWER_IN_MW_SHIFT) & \ + POWER_IN_MW_MASK) + +// Performance protocol attributes return values. +typedef struct { + UINT32 Attributes; + UINT64 StatisticsAddress; + UINT32 StatisticsLen; +} SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES; + +#define SCMI_PERF_SUPPORT_LVL_CHANGE_NOTIFY(Attr) ((Attr >> 28) & 0x1) +#define SCMI_PERF_SUPPORT_LIM_CHANGE_NOTIFY(Attr) ((Attr >> 29) & 0x1) +#define SCMI_PERF_SUPPORT_SET_LVL(Attr) ((Attr >> 30) & 0x1) +#define SCMI_PERF_SUPPORT_SET_LIM(Attr) ((Attr >> 31) & 0x1) +#define SCMI_PERF_RATE_LIMIT(RateLimit) (RateLimit & 0xFFF) + +// Performance protocol domain attributes. +typedef struct { + UINT32 Attributes; + UINT32 RateLimit; + UINT32 SustainedFreq; + UINT32 SustainedPerfLevel; + UINT8 Name[SCMI_MAX_STR_LEN]; +} SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES; + +// Worst case latency in microseconds, Bits[15:0] +#define PERF_LATENCY_MASK 0xFFFF +#define SCMI_PERFORMANCE_PROTOCOL_LATENCY(Latency) (Latency & PERF_LATENCY_MASK) + +// Performance protocol performance level. +typedef struct { + UINT32 Level; + UINT32 PowerCost; + UINT32 Latency; +} SCMI_PERFORMANCE_LEVEL; + +// Performance protocol performance limit. +typedef struct { + UINT32 RangeMax; + UINT32 RangeMin; +} SCMI_PERFORMANCE_LIMITS; + +#pragma pack() + +/** Return version of the performance management protocol supported by SCP. + firmware. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + + @param[out] Version Version of the supported SCMI performance management + protocol. + + @retval EFI_SUCCESS The version is returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_PERFORMANCE_GET_VERSION) ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + OUT UINT32 *Version + ); + +/** Return protocol attributes of the performance management protocol. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + + @param[out] Attributes Protocol attributes. + + @retval EFI_SUCCESS Protocol attributes are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_PERFORMANCE_GET_ATTRIBUTES) ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES *Attributes + + ); + +/** Return performance domain attributes. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + + @param[out] Attributes Performance domain attributes. + + @retval EFI_SUCCESS Domain attributes are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_PERFORMANCE_GET_DOMAIN_ATTRIBUTES) ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES *DomainAttributes + ); + +/** Return list of performance domain levels of a given domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + + @param[out] NumLevels Total number of levels a domain can support. + + @param[in,out] LevelArraySize Size of the performance level array. + + @param[out] LevelArray Array of the performance levels. + + @retval EFI_SUCCESS Domain levels are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result. + It has been updated to the size needed. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_PERFORMANCE_DESCRIBE_LEVELS) ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + OUT UINT32 *NumLevels, + IN OUT UINT32 *LevelArraySize, + OUT SCMI_PERFORMANCE_LEVEL *LevelArray + ); + +/** Set performance limits of a domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + @param[in] Limit Performance limit to set. + + @retval EFI_SUCCESS Performance limits set successfully. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_PERFORMANCE_LIMITS_SET) ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + IN SCMI_PERFORMANCE_LIMITS *Limits + ); + +/** Get performance limits of a domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + + @param[out] Limit Performance Limits of the domain. + + @retval EFI_SUCCESS Performance limits are returned. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_PERFORMANCE_LIMITS_GET) ( + SCMI_PERFORMANCE_PROTOCOL *This, + UINT32 DomainId, + SCMI_PERFORMANCE_LIMITS *Limits + ); + +/** Set performance level of a domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + @param[in] Level Performance level of the domain. + + @retval EFI_SUCCESS Performance level set successfully. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_PERFORMANCE_LEVEL_SET) ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + IN UINT32 Level + ); + +/** Get performance level of a domain. + + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. + @param[in] DomainId Identifier for the performance domain. + + @param[out] Level Performance level of the domain. + + @retval EFI_SUCCESS Performance level got successfully. + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. + @retval !(EFI_SUCCESS) Other errors. +**/ +typedef +EFI_STATUS +(EFIAPI *SCMI_PERFORMANCE_LEVEL_GET) ( + IN SCMI_PERFORMANCE_PROTOCOL *This, + IN UINT32 DomainId, + OUT UINT32 *Level + ); + +typedef struct _SCMI_PERFORMANCE_PROTOCOL { + SCMI_PERFORMANCE_GET_VERSION GetVersion; + SCMI_PERFORMANCE_GET_ATTRIBUTES GetProtocolAttributes; + SCMI_PERFORMANCE_GET_DOMAIN_ATTRIBUTES GetDomainAttributes; + SCMI_PERFORMANCE_DESCRIBE_LEVELS DescribeLevels; + SCMI_PERFORMANCE_LIMITS_SET LimitsSet; + SCMI_PERFORMANCE_LIMITS_GET LimitsGet; + SCMI_PERFORMANCE_LEVEL_SET LevelSet; + SCMI_PERFORMANCE_LEVEL_GET LevelGet; +} SCMI_PERFORMANCE_PROTOCOL; + +typedef enum { + SCMI_MESSAGE_ID_PERFORMANCE_DOMAIN_ATTRIBUTES = 0x3, + SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS = 0x4, + SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET = 0x5, + SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET = 0x6, + SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET = 0x7, + SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET = 0x8, +} SCMI_MESSAGE_ID_PERFORMANCE; + +#endif /* ARM_SCMI_PERFORMANCE_PROTOCOL_H_ */ +