Hmm, I did find a few minor things below that I need to hear back on
before pushing.

On Tue, Mar 20, 2018 at 04:12:12PM +0000, Girish Pathak wrote:
> This change introduces a new SCMI protocol driver for
> Arm systems. The driver currently supports only clock
> and performance management protocols. Other protocols
> will be added as and when needed.
> 
> Clock management protocol is used to configure various clocks
> available on the platform e.g. HDLCD clock on the Juno platforms.
> 
> Whereas performance management protocol allows adjustment
> of various performance domains. Currently this is used to evaluate
> performance of the Juno platform.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Girish Pathak <girish.pat...@arm.com>
> Signed-off-by: Evan Lloyd <evan.ll...@arm.com>
> ---
> 
> Notes:
>     v3:
>     - Please rename ArmMtl.h to ArmMtlLibi.h, and
>       declare it as a library class in the package file.          [Ard]
>     
>       Done, however ArmMtlLib.h is now part of earlier commit     [Girish]
>     
>     - Move ArmScmiDxe to ArmPkg from ArmPlatformPkg               [Ard]
>     
>       Done                                                        [Girish]
>     
>     - Declare gArmScmiBaseProtocolGuid and similar
>       protocols Guids in ArmPkg.dec                               [Ard]
>     
>       Done                                                        [Girish]
>     
>     - Replace flexible array member [] with [1]                   [Ard]
>     
>       Done                                                        [Girish]
>     
>     - Move protocol init function which are not part of
>       of protocol like  ScmiBaseProtocolInit elsewhere            [Ard]
>     
>       Done                                                        [Girish]
>     
>     - Please don't put stuff in Include/Drivers.                  [Ard]
>     
>       Moved headers to Include/Protocol.                          [Girish]
> 
>  ArmPkg/ArmPkg.dec                                             |  13 +
>  ArmPkg/ArmPkg.dsc                                             |   6 +-
>  ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h        |  46 ++
>  ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h       |  84 ++++
>  ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf                      |  53 +++
>  ArmPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h |  55 +++
>  ArmPkg/Drivers/ArmScmiDxe/Scmi.c                              | 262 
> +++++++++++
>  ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c                  | 318 
> ++++++++++++++
>  ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c                 | 418 
> ++++++++++++++++++
>  ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c                           | 138 ++++++
>  ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h                           |  41 ++
>  ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c           | 457 
> ++++++++++++++++++++
>  ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h                       | 174 ++++++++
>  ArmPkg/Include/Protocol/ArmScmi.h                             |  27 ++
>  ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h                 | 174 ++++++++
>  ArmPkg/Include/Protocol/ArmScmiClockProtocol.h                | 218 
> ++++++++++
>  ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h          | 265 
> ++++++++++++
>  17 files changed, 2748 insertions(+), 1 deletion(-)
> 
> diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
> index 
> 881751d81c6384a3eb0b4c180c76d01a58266a74..16f7e40046429142b44b526043b61a3d5e089d2c
>  100644
> --- a/ArmPkg/ArmPkg.dec
> +++ b/ArmPkg/ArmPkg.dec
> @@ -51,6 +51,19 @@ [Guids.common]
>  
>    gArmGicDxeFileGuid = { 0xde371f7c, 0xdec4, 0x4d21, { 0xad, 0xf1, 0x59, 
> 0x3a, 0xbc, 0xc1, 0x58, 0x82 } }
>  
> +[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 
> 526909458e0d80dbc5a65c8ad12ec1095dda48d2..22332090db7111e0668607a16288cefc1bace926
>  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.<BR>
> -# Copyright (c) 2011 - 2015, ARM Ltd. All rights reserved.<BR>
> +# Copyright (c) 2011 - 2018, ARM Ltd. All rights reserved.<BR>
>  # Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
>  #
>  #    This program and the accompanying materials
> @@ -87,6 +87,8 @@ [LibraryClasses.common]
>    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 @@ [Components.common]
>    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 
> 0000000000000000000000000000000000000000..79c057d44128008ec276e3d58d8f1098c6a779b2
> --- /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 
> 0000000000000000000000000000000000000000..71245c16475d4d38d6dc66571b3fe3520c1cf1da
> --- /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)

I'll decrease indentation of above line by one unless someone objects?

> +
> +// 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 
> 0000000000000000000000000000000000000000..05ce9c04ce468d74e5c6d38739f9056f3fc48694
> --- /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 
> 0000000000000000000000000000000000000000..4514f45a9f5dd960d2844a19b57a91b93149f1b9
> --- /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 <Protocol/ArmScmiPerformanceProtocol.h>
> +
> +// 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 
> 0000000000000000000000000000000000000000..1e279f69cf615428dbb6477b8ac7de3258628df3
> --- /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 <Library/ArmMtlLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#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 
> 0000000000000000000000000000000000000000..0829438c82ec5723cfbbf9c411d10fcf22a22d89
> --- /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 <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/ArmScmiBaseProtocol.h>
> +
> +#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 
> 0000000000000000000000000000000000000000..fe7edd2a8c8b7761fb3008e66d192ef1ee1ade2e
> --- /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 <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/ArmScmiClockProtocol.h>
> +
> +#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));
> +}

Suggestion for future improvement: make this a macro in Base.h
The SIGNATURE_64 macro in there would already benefit from it.

> +
> +/** 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;

Missing space (will add before committing).

> +  }
> +
> +  *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 = ((UINT64)ClockRate->High << 32) | ClockRate->Low;

Should this not use the helper function?
I could fix that up before committing, but would like confirmation on that.

> +
> +  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 
> 0000000000000000000000000000000000000000..2920c6f6f33c5bb8ac00c903a0b199ba5f06f4de
> --- /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 <Base.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/ArmScmiBaseProtocol.h>
> +#include <Protocol/ArmScmiClockProtocol.h>
> +#include <Protocol/ArmScmiPerformanceProtocol.h>
> +
> +#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 
> 0000000000000000000000000000000000000000..29cdde173659c701116b021a3c437a92b473e4e5
> --- /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 
> 0000000000000000000000000000000000000000..ac32442ad838040721fd62faa806e82184f2b288
> --- /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 <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/ArmScmiPerformanceProtocol.h>
> +#include <string.h>
> +
> +#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;
> +  }
> +
> +  memcpy (

Urgh, missed this one on previous passes.
Surely this should be 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;
> +  }
> +
> +  memcpy (

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++) {
> +       memcpy (

CopyMem?

/
    Leif

> +         &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 
> 0000000000000000000000000000000000000000..df03655b8b021fe5fd63ceab0dd414906d2fb248
> --- /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 
> 0000000000000000000000000000000000000000..239abb97064578c949614f79a6a33fe1881c3c68
> --- /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 
> 0000000000000000000000000000000000000000..ecc41f2181ecc9f835950ab46c7cfd2e476a7073
> --- /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 <Protocol/ArmScmi.h>
> +
> +#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 
> 0000000000000000000000000000000000000000..3db26cb0641c7377c022a8e00be9a51ee5dc7361
> --- /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 <Protocol/ArmScmi.h>
> +
> +#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 
> 0000000000000000000000000000000000000000..1d1af6f8bee0c00bbe6b4774036c87c988a4f4af
> --- /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 <Protocol/ArmScmi.h>
> +
> +#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_ */
> +
> -- 
> 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
> 
> 
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to