[edk2] [PATCH v2 13/13] ArmPlatformPkg: Introduce SCMI protocol

evan.lloyd@arm.com posted 13 patches 7 years ago
[edk2] [PATCH v2 13/13] ArmPlatformPkg: Introduce SCMI protocol
Posted by evan.lloyd@arm.com 7 years ago
From: Girish Pathak <girish.pathak@arm.com>

This change introduces a new SCMI protocol driver for
Arm Platforms. 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 the HDLCD clock
on Juno platforms.

Whereas performance management protocol allows adjustment
of various performance domains to evaluate performance of the
Juno platform.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Girish Pathak <girish.pathak@arm.com>
---
 ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf                      |  48 ++
 ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h        |  29 ++
 ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h       |  69 +++
 ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h |  39 ++
 ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.h                           |  41 ++
 ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPrivate.h                       | 174 ++++++++
 ArmPlatformPkg/Include/Drivers/ArmScmi.h                              |  27 ++
 ArmPlatformPkg/Include/Drivers/ArmScmiBaseProtocol.h                  | 182 ++++++++
 ArmPlatformPkg/Include/Drivers/ArmScmiClockProtocol.h                 | 225 ++++++++++
 ArmPlatformPkg/Include/Drivers/ArmScmiPerformanceProtocol.h           | 274 ++++++++++++
 ArmPlatformPkg/Include/Library/ArmMtl.h                               | 132 ++++++
 ArmPlatformPkg/Drivers/ArmScmiDxe/Scmi.c                              | 261 +++++++++++
 ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c                  | 320 ++++++++++++++
 ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c                 | 419 ++++++++++++++++++
 ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.c                           | 135 ++++++
 ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c           | 457 ++++++++++++++++++++
 16 files changed, 2832 insertions(+)

diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
new file mode 100644
index 0000000000000000000000000000000000000000..ad7c363c9d6621df36fb7beddff9e2ae28127c52
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
@@ -0,0 +1,48 @@
+#/** @file
+#
+#  Copyright (c) 2017, 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
+  ArmMtl
+  DebugLib
+  IoLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Depex]
+  TRUE
+
diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h
new file mode 100644
index 0000000000000000000000000000000000000000..88d47b9efb49f02dbadd0b6d76dac7a991df2124
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h
@@ -0,0 +1,29 @@
+/** @file
+
+  Copyright (c) 2017, 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
+  UINT8 Protocols[];
+} BASE_DISCOVER_LIST;
+
+#endif /* ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_ */
diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h
new file mode 100644
index 0000000000000000000000000000000000000000..2807b6b476ac1b8cf821a29ca7a59a78e9188c52
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h
@@ -0,0 +1,69 @@
+/** @file
+
+  Copyright (c) 2017, ARM Limited. All rights reserved.
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  System Control and Management Interface V1.0
+    http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
+    DEN0056A_System_Control_and_Management_Interface.pdf
+**/
+
+#ifndef ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_
+#define ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_
+
+#pragma pack(1)
+
+// Clock rate in two 32bit words.
+typedef struct {
+  UINT32 Low;
+  UINT32 High;
+} CLOCK_RATE_DWORD;
+
+// Format of the returned rate array. Linear or Non-linear,.RatesFlag Bit[12]
+#define RATE_FORMAT_SHIFT           12
+#define RATE_FORMAT_MASK            0x0001
+#define RATE_FORMAT(RatesFlags)     ((RatesFlags >> RATE_FORMAT_SHIFT)  \
+                                      & RATE_FORMAT_MASK)
+
+// Number of remaining rates after a call to the SCP, RatesFlag Bits[31:16]
+#define NUM_REMAIN_RATES_SHIFT        16
+#define NUM_REMAIN_RATES(RatesFlags)  ((RatesFlags >> NUM_REMAIN_RATES_SHIFT))
+
+// Number of rates that are returned by a call.to the SCP, RatesFlag Bits[11:0]
+#define NUM_RATES_MASK              0x0FFF
+#define NUM_RATES(RatesFlags)       (RatesFlags & NUM_RATES_MASK)
+
+// Return values for the CLOCK_DESCRIBER_RATE command.
+typedef struct {
+  UINT32 NumRatesFlags;
+  CLOCK_RATE_DWORD Rates[];
+} 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()
+
+#endif /* ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_ */
diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h
new file mode 100644
index 0000000000000000000000000000000000000000..99fe80ae30bc818edef9125e5e8a2d11322feb41
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h
@@ -0,0 +1,39 @@
+/** @file
+
+  Copyright (c) 2017, 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 <Drivers/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;
+  SCMI_PERFORMANCE_LEVEL PerfLevel[]; // Offset to array of performance levels
+} PERF_DESCRIBE_LEVELS;
+
+#endif /* ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ */
diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.h
new file mode 100644
index 0000000000000000000000000000000000000000..a2ce4bf9022cee79e0486db3cf9b4fdddf481081
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.h
@@ -0,0 +1,41 @@
+/** @file
+
+  Copyright (c) 2017, 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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPrivate.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPrivate.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca3a712c1afd3e3bd25f831f57aab7e6bff1cddb
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPrivate.h
@@ -0,0 +1,174 @@
+/** @file
+
+  Copyright (c) 2017, 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/ArmPlatformPkg/Include/Drivers/ArmScmi.h b/ArmPlatformPkg/Include/Drivers/ArmScmi.h
new file mode 100644
index 0000000000000000000000000000000000000000..04ea3de5b34157ed459ee47440abbcaa7114e93a
--- /dev/null
+++ b/ArmPlatformPkg/Include/Drivers/ArmScmi.h
@@ -0,0 +1,27 @@
+/** @file
+
+  Copyright (c) 2017, 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/ArmPlatformPkg/Include/Drivers/ArmScmiBaseProtocol.h b/ArmPlatformPkg/Include/Drivers/ArmScmiBaseProtocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8fab57fc354f14e79287520f6c8f05eb1eff141
--- /dev/null
+++ b/ArmPlatformPkg/Include/Drivers/ArmScmiBaseProtocol.h
@@ -0,0 +1,182 @@
+/** @file
+
+  Copyright (c) 2017, 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 <Drivers/ArmScmi.h>
+
+#define BASE_PROTOCOL_VERSION  0x10000
+
+#define NUM_PROTOCOL_MASK      0xFFU
+#define NUM_AGENT_MASK         0xFFU
+
+#define NUM_AGENT_SHIFT        0x8
+
+// Returns total protocols that are implemented (excluding the Base protocol)
+#define SCMI_TOTAL_PROTOCOLS(Attr) (Attr & NUM_PROTOCOL_MASK)
+
+// Returns 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;
+
+/** 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_H_ */
+
diff --git a/ArmPlatformPkg/Include/Drivers/ArmScmiClockProtocol.h b/ArmPlatformPkg/Include/Drivers/ArmScmiClockProtocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..a97728e4dfe8efc3cd8dc29dc94987c1cc6c6a80
--- /dev/null
+++ b/ArmPlatformPkg/Include/Drivers/ArmScmiClockProtocol.h
@@ -0,0 +1,225 @@
+/** @file
+
+  Copyright (c) 2017, 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 <Drivers/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 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;
+
+/** 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_H_ */
+
diff --git a/ArmPlatformPkg/Include/Drivers/ArmScmiPerformanceProtocol.h b/ArmPlatformPkg/Include/Drivers/ArmScmiPerformanceProtocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb4aa6bf71df86cfd7a0dabb354112c5a38c978f
--- /dev/null
+++ b/ArmPlatformPkg/Include/Drivers/ArmScmiPerformanceProtocol.h
@@ -0,0 +1,274 @@
+/** @file
+
+  Copyright (c) 2017, 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 <Drivers/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)
+// Power values expressed in mW, 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;
+
+/** 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_H_ */
+
diff --git a/ArmPlatformPkg/Include/Library/ArmMtl.h b/ArmPlatformPkg/Include/Library/ArmMtl.h
new file mode 100644
index 0000000000000000000000000000000000000000..9be65cfa0a1dcf0d984f29e5d95aedf5e0afac2b
--- /dev/null
+++ b/ArmPlatformPkg/Include/Library/ArmMtl.h
@@ -0,0 +1,132 @@
+/** @file
+
+  Copyright (c) 2017, 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_MTL_H_
+#define ARM_MTL_H_
+
+// Ideally we don't need packed struct. However we can't rely on compilers
+#pragma pack(1)
+
+typedef struct {
+  UINT32 Reserved1;
+  UINT32 ChannelStatus;
+  UINT64 Reserved2;
+  UINT32 Flags;
+  UINT32 Length;
+  UINT32 MessageHeader;
+  UINT32 Payload[];    // size less object gives offset to payload.
+} MTL_MAILBOX;
+
+#pragma pack()
+
+// Channel Type, Low-priority, and High-priority
+typedef enum {
+  MTL_CHANNEL_TYPE_LOW = 0,
+  MTL_CHANNEL_TYPE_HIGH = 1
+} MTL_CHANNEL_TYPE;
+
+typedef struct {
+  UINT64 PhysicalAddress;
+  UINT32 ModifyMask;
+  UINT32 PreserveMask;
+} MTL_DOORBELL;
+
+typedef struct {
+  MTL_CHANNEL_TYPE ChannelType;
+  MTL_MAILBOX      * CONST MailBox;
+  MTL_DOORBELL     DoorBell;
+} MTL_CHANNEL;
+
+/** Wait until channel is free.
+
+  @param[in] Channel                Pointer to a channel.
+  @param[in] TimeOutInMicroSeconds  Time out in micro seconds.
+
+  @retval EFI_SUCCESS               Channel is free.
+  @retval EFI_TIMOUT                Timeout error.
+**/
+EFI_STATUS
+MtlWaitUntilChannelFree (
+  IN MTL_CHANNEL  *Channel,
+  IN UINT64       TimeOutInMicroSeconds
+  );
+
+/** Return the address of the message payload.
+
+  @param[in] Channel   Pointer to a channel.
+
+  @retval UINT32*      Pointer to the payload.
+**/
+UINT32*
+MtlGetChannelPayload (
+  IN MTL_CHANNEL  *Channel
+  );
+
+/** Return pointer to a channel for the requested channel type.
+
+  @param[in] ChannelType        ChannelType, Low or High priority channel.
+                                MTL_CHANNEL_TYPE_LOW or
+                                MTL_CHANNEL_TYPE_HIGH
+
+  @param[out] Channel           Holds pointer to the channel.
+
+  @retval EFI_SUCCESS           Pointer to channel is returned.
+  @retval EFI_UNSUPPORTED       Requested channel type not supported.
+**/
+EFI_STATUS
+MtlGetChannel (
+  IN  MTL_CHANNEL_TYPE  ChannelType,
+  OUT MTL_CHANNEL       **Channel
+  );
+
+
+/** Mark the channel busy and ring the doorbell.
+
+  @param[in] Channel               Pointer to a channel.
+  @param[in] MessageHeader         Message header.
+
+  @param[out] PayloadLength        Message length.
+
+  @retval EFI_SUCCESS              Message sent successfully.
+  @retval EFI_DEVICE_ERROR         Channel is busy.
+**/
+EFI_STATUS
+MtlSendMessage (
+  IN  MTL_CHANNEL  *Channel,
+  IN  UINT32       MessageHeader,
+  OUT UINT32       PayloadLength
+  );
+
+/** Wait for a response on a channel.
+
+  If channel is free after sending message, it implies SCP responded
+  with a response on the channel.
+
+  @param[in] Channel               Pointer to a channel.
+
+  @retval EFI_SUCCESS              Message received successfully.
+  @retval EFI_TIMOUT               Timeout error.
+**/
+EFI_STATUS
+MtlReceiveMessage (
+  IN  MTL_CHANNEL  *Channel,
+  OUT UINT32       *MessageHeader,
+  OUT UINT32       *PayloadLength
+  );
+
+#endif  /* ARM_MTL_H_ */
+
diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/Scmi.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/Scmi.c
new file mode 100644
index 0000000000000000000000000000000000000000..8abbd90ce7bd5420cf81f89a4680e5563d7af085
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/Scmi.c
@@ -0,0 +1,261 @@
+/** @file
+
+  Copyright (c) 2017, 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/ArmMtl.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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c
new file mode 100644
index 0000000000000000000000000000000000000000..144df459e9238b5e08c87ad12999a5491679d1fb
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c
@@ -0,0 +1,320 @@
+/** @file
+
+  Copyright (c) 2017, 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 <Drivers/ArmScmiBaseProtocol.h>
+
+#include "ArmScmiBaseProtocolPrivate.h"
+#include "ScmiPrivate.h"
+
+EFI_GUID gArmScmiBaseProtocolGuid = ARM_SCMI_BASE_PROTOCOL_GUID;
+
+/** 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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c
new file mode 100644
index 0000000000000000000000000000000000000000..895f3f6c5dccbd24e98ed73fa08c41a369d83f43
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c
@@ -0,0 +1,419 @@
+/** @file
+
+  Copyright (c) 2017, 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 <Drivers/ArmScmiClockProtocol.h>
+
+#include "ArmScmiClockProtocolPrivate.h"
+#include "ScmiPrivate.h"
+
+EFI_GUID gArmScmiClockProtocolGuid = ARM_SCMI_CLOCK_PROTOCOL_GUID;
+
+/** Convert to 64 bit value from two 32 bit words.
+
+  @param[in] Low   Lower 32 bits.
+  @param[in] High  Higher 32 bits.
+
+  @retval UINT64   64 bit value.
+**/
+STATIC
+UINT64
+ConvertTo64Bit (
+  IN UINT32 Low,
+  IN UINT32 High
+  )
+{
+   return (Low | ((UINT64)High << 32));
+}
+
+/** Return version of the clock management protocol supported by SCP firmware.
+
+  @param[in]  This     A Pointer to SCMI_CLOCK_PROTOCOL Instance.
+
+  @param[out] Version  Version of the supported SCMI Clock management protocol.
+
+  @retval EFI_SUCCESS       The version is returned.
+  @retval EFI_DEVICE_ERROR  SCP returns an SCMI error.
+  @retval !(EFI_SUCCESS)    Other errors.
+**/
+STATIC
+EFI_STATUS
+ClockGetVersion (
+  IN  SCMI_CLOCK_PROTOCOL  *This,
+  OUT UINT32               *Version
+  )
+{
+  return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_CLOCK, Version);
+}
+
+/** Return total number of clock devices supported by the clock management
+  protocol.
+
+  @param[in]  This         A Pointer to SCMI_CLOCK_PROTOCOL Instance.
+
+  @param[out] TotalClocks  Total number of clocks supported.
+
+  @retval EFI_SUCCESS       Total number of clocks supported is returned.
+  @retval EFI_DEVICE_ERROR  SCP returns an SCMI error.
+  @retval !(EFI_SUCCESS)    Other errors.
+**/
+STATIC
+EFI_STATUS
+ClockGetTotalClocks (
+  IN  SCMI_CLOCK_PROTOCOL  *This,
+  OUT UINT32               *TotalClocks
+  )
+{
+  EFI_STATUS  Status;
+  UINT32     *ReturnValues;
+
+  Status = ScmiGetProtocolAttributes (SCMI_PROTOCOL_ID_CLOCK, &ReturnValues);
+  if (EFI_ERROR (Status)) {
+   return Status;
+  }
+
+  *TotalClocks = SCMI_CLOCK_PROTOCOL_TOTAL_CLKS (ReturnValues[0]);
+
+  return EFI_SUCCESS;
+}
+
+/** Return attributes of a clock device.
+
+  @param[in]  This        A Pointer to SCMI_CLOCK_PROTOCOL Instance.
+  @param[in]  ClockId     Identifier for the clock device.
+
+  @param[out] Enabled         If TRUE, the clock device is enabled.
+  @param[out] ClockAsciiName  A NULL terminated ASCII string with the clock
+                              name, of up to 16 bytes.
+
+  @retval EFI_SUCCESS          Clock device attributes are returned.
+  @retval EFI_DEVICE_ERROR     SCP returns an SCMI error.
+  @retval !(EFI_SUCCESS)       Other errors.
+**/
+STATIC
+EFI_STATUS
+ClockGetClockAttributes (
+  IN  SCMI_CLOCK_PROTOCOL  *This,
+  IN  UINT32               ClockId,
+  OUT BOOLEAN              *Enabled,
+  OUT CHAR8                *ClockAsciiName
+  )
+{
+  EFI_STATUS          Status;
+
+  UINT32              *MessageParams;
+  CLOCK_ATTRIBUTES    *ClockAttributes;
+  SCMI_COMMAND        Cmd;
+  UINT32              PayloadLength;
+
+  Status = ScmiCommandGetPayload (&MessageParams);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *MessageParams = ClockId;
+
+  Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK;
+  Cmd.MessageId  = SCMI_MESSAGE_ID_CLOCK_ATTRIBUTES;
+
+  PayloadLength = sizeof (ClockId);
+
+  Status = ScmiCommandExecute (
+             &Cmd,
+             &PayloadLength,
+             (UINT32**)&ClockAttributes
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+   // TRUE if bit 0 of ClockAttributes->Attributes is set.
+  *Enabled = CLOCK_ENABLED (ClockAttributes->Attributes);
+
+  AsciiStrCpyS (
+    ClockAsciiName,
+    SCMI_MAX_STR_LEN,
+    (CONST CHAR8*)ClockAttributes->ClockName
+    );
+
+  return EFI_SUCCESS;
+}
+
+/** Return list of rates supported by a given clock device.
+
+  @param[in] This        A pointer to SCMI_CLOCK_PROTOCOL Instance.
+  @param[in] ClockId     Identifier for the clock device.
+
+  @param[out] Format      SCMI_CLOCK_RATE_FORMAT_DISCRETE: Clock device
+                          supports range of clock rates which are non-linear.
+
+                          SCMI_CLOCK_RATE_FORMAT_LINEAR: Clock device supports
+                          range of linear clock rates from Min to Max in steps.
+
+  @param[out] TotalRates  Total number of rates.
+
+  @param[in,out] RateArraySize  Size of the RateArray.
+
+  @param[out] RateArray   List of clock rates.
+
+  @retval EFI_SUCCESS          List of clock rates is returned.
+  @retval EFI_DEVICE_ERROR     SCP returns an SCMI error.
+  @retval EFI_BUFFER_TOO_SMALL RateArraySize is too small for the result.
+                               It has been updated to the size needed.
+  @retval !(EFI_SUCCESS)       Other errors.
+**/
+STATIC
+EFI_STATUS
+ClockDescribeRates (
+  IN     SCMI_CLOCK_PROTOCOL     *This,
+  IN     UINT32                   ClockId,
+  OUT    SCMI_CLOCK_RATE_FORMAT  *Format,
+  OUT    UINT32                  *TotalRates,
+  IN OUT UINT32                  *RateArraySize,
+  OUT    SCMI_CLOCK_RATE         *RateArray
+  )
+{
+  EFI_STATUS             Status;
+
+  UINT32                 PayloadLength;
+  SCMI_COMMAND           Cmd;
+  UINT32                 *MessageParams;
+  CLOCK_DESCRIBE_RATES   *DescribeRates;
+  CLOCK_RATE_DWORD       *Rate;
+
+  UINT32                 RequiredArraySize = 0;
+  UINT32                 RateIndex = 0;
+  UINT32                 RateNo;
+  UINT32                 RateOffset;
+
+  *TotalRates = 0;
+
+  Status = ScmiCommandGetPayload (&MessageParams);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK;
+  Cmd.MessageId  = SCMI_MESSAGE_ID_CLOCK_DESCRIBE_RATES;
+
+  *MessageParams++  = ClockId;
+
+  do {
+
+    *MessageParams = RateIndex;
+
+    // Set Payload length, note PayloadLength is a IN/OUT parameter.
+    PayloadLength  = sizeof (ClockId) + sizeof (RateIndex);
+
+    // Execute and wait for response on a SCMI channel.
+    Status = ScmiCommandExecute (
+               &Cmd,
+               &PayloadLength,
+               (UINT32**)&DescribeRates
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    if (*TotalRates == 0) {
+      // In the first iteration we will get number of returned rates and number
+      // of remaining rates. With this information calculate required size
+      // for rate array. If provided RateArraySize is less, return an
+      // error.
+
+      *Format = RATE_FORMAT (DescribeRates->NumRatesFlags);
+
+      *TotalRates = NUM_RATES (DescribeRates->NumRatesFlags)
+                    + NUM_REMAIN_RATES (DescribeRates->NumRatesFlags);
+
+      if (*Format == SCMI_CLOCK_RATE_FORMAT_DISCRETE) {
+         RequiredArraySize = (*TotalRates) * sizeof (UINT64);
+      } else {
+         // We need to return triplet of 64 bit value for each rate
+         RequiredArraySize = (*TotalRates) * 3 * sizeof (UINT64);
+      }
+
+      if (RequiredArraySize > (*RateArraySize)) {
+        *RateArraySize = RequiredArraySize;
+        return EFI_BUFFER_TOO_SMALL;
+      }
+    }
+
+    RateOffset = 0;
+
+    if (*Format == SCMI_CLOCK_RATE_FORMAT_DISCRETE) {
+      for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) {
+        Rate = &DescribeRates->Rates[RateOffset++];
+        // Non-linear discrete rates.
+        RateArray[RateIndex++].Rate = ConvertTo64Bit (Rate->Low, Rate->High);
+      }
+    } else {
+      for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) {
+        // Linear clock rates from minimum to maximum in steps
+        // Minimum clock rate.
+        Rate = &DescribeRates->Rates[RateOffset++];
+        RateArray[RateIndex].Min = ConvertTo64Bit (Rate->Low, Rate->High);
+
+        Rate = &DescribeRates->Rates[RateOffset++];
+        // Maximum clock rate.
+        RateArray[RateIndex].Max = ConvertTo64Bit (Rate->Low, Rate->High);
+
+        Rate = &DescribeRates->Rates[RateOffset++];
+        // Step.
+        RateArray[RateIndex++].Step = ConvertTo64Bit (Rate->Low, Rate->High);
+      }
+    }
+  } while (NUM_REMAIN_RATES (DescribeRates->NumRatesFlags) != 0);
+
+  // Update RateArraySize with RequiredArraySize.
+  *RateArraySize = RequiredArraySize;
+
+  return EFI_SUCCESS;
+}
+
+/** Get clock rate.
+
+  @param[in]  This        A Pointer to SCMI_CLOCK_PROTOCOL Instance.
+  @param[in]  ClockId     Identifier for the clock device.
+
+  @param[out]  Rate       Clock rate.
+
+  @retval EFI_SUCCESS          Clock rate is returned.
+  @retval EFI_DEVICE_ERROR     SCP returns an SCMI error.
+  @retval !(EFI_SUCCESS)       Other errors.
+**/
+STATIC
+EFI_STATUS
+ClockRateGet (
+  IN  SCMI_CLOCK_PROTOCOL  *This,
+  IN  UINT32               ClockId,
+  OUT UINT64               *Rate
+  )
+{
+  EFI_STATUS     Status;
+
+  UINT32            *MessageParams;
+  CLOCK_RATE_DWORD  *ClockRate;
+  SCMI_COMMAND      Cmd;
+
+  UINT32         PayloadLength;
+
+  Status = ScmiCommandGetPayload (&MessageParams);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Fill arguments for clock protocol command.
+  *MessageParams  = ClockId;
+
+  Cmd.ProtocolId  = SCMI_PROTOCOL_ID_CLOCK;
+  Cmd.MessageId   = SCMI_MESSAGE_ID_CLOCK_RATE_GET;
+
+  PayloadLength = sizeof (ClockId);
+
+  // Execute and wait for response on a SCMI channel.
+  Status = ScmiCommandExecute (
+             &Cmd,
+             &PayloadLength,
+             (UINT32**)&ClockRate
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *Rate = ((UINT64)ClockRate->High << 32) | ClockRate->Low;
+
+  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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.c
new file mode 100644
index 0000000000000000000000000000000000000000..b11d232d7e910f7ed0a165fb4e22e207c2c3e607
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.c
@@ -0,0 +1,135 @@
+/** @file
+
+  Copyright (c) 2017, 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 <Drivers/ArmScmiBaseProtocol.h>
+#include <Drivers/ArmScmiClockProtocol.h>
+#include <Drivers/ArmScmiPerformanceProtocol.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "ScmiPrivate.h"
+#include "ScmiDxe.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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
new file mode 100644
index 0000000000000000000000000000000000000000..3946dc21005430c430605bf60fb40fb99e2a0178
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
@@ -0,0 +1,457 @@
+/** @file
+
+  Copyright (c) 2017, 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 <Drivers/ArmScmiPerformanceProtocol.h>
+#include <string.h>
+
+#include "ArmScmiPerformanceProtocolPrivate.h"
+#include "ScmiPrivate.h"
+
+EFI_GUID gArmScmiPerformanceProtocolGuid = ARM_SCMI_PERFORMANCE_PROTOCOL_GUID;
+
+/** 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 (
+    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 (
+    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;
+
+  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;
+    }
+
+    if (RequiredSize == 0) {
+      *NumLevels = NUM_PERF_LEVELS (Levels->NumLevels)
+                   + NUM_REMAIN_PERF_LEVELS (Levels->NumLevels);
+      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 < NUM_PERF_LEVELS (Levels->NumLevels);
+         LevelNo++) {
+       memcpy (
+         &LevelArray[LevelIndex++],
+         &Levels->PerfLevel[LevelNo],
+         sizeof (SCMI_PERFORMANCE_LEVEL)
+         );
+    }
+
+  } while (NUM_REMAIN_PERF_LEVELS (Levels->NumLevels) != 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
+                );
+}
-- 
Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH v2 13/13] ArmPlatformPkg: Introduce SCMI protocol
Posted by Ard Biesheuvel 7 years ago
, couOn 22 December 2017 at 18:34,  <evan.lloyd@arm.com> wrote:
> From: Girish Pathak <girish.pathak@arm.com>
>
> This change introduces a new SCMI protocol driver for
> Arm Platforms. 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 the HDLCD clock
> on Juno platforms.
>
> Whereas performance management protocol allows adjustment
> of various performance domains to evaluate performance of the
> Juno platform.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Girish Pathak <girish.pathak@arm.com>
> ---
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf                      |  48 ++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h        |  29 ++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h       |  69 +++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h |  39 ++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.h                           |  41 ++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPrivate.h                       | 174 ++++++++
>  ArmPlatformPkg/Include/Drivers/ArmScmi.h                              |  27 ++
>  ArmPlatformPkg/Include/Drivers/ArmScmiBaseProtocol.h                  | 182 ++++++++
>  ArmPlatformPkg/Include/Drivers/ArmScmiClockProtocol.h                 | 225 ++++++++++
>  ArmPlatformPkg/Include/Drivers/ArmScmiPerformanceProtocol.h           | 274 ++++++++++++
>  ArmPlatformPkg/Include/Library/ArmMtl.h                               | 132 ++++++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/Scmi.c                              | 261 +++++++++++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c                  | 320 ++++++++++++++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c                 | 419 ++++++++++++++++++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.c                           | 135 ++++++
>  ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c           | 457 ++++++++++++++++++++
>  16 files changed, 2832 insertions(+)
>
> diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..ad7c363c9d6621df36fb7beddff9e2ae28127c52
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
> @@ -0,0 +1,48 @@
> +#/** @file
> +#
> +#  Copyright (c) 2017, 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
> +  ArmMtl
> +  DebugLib
> +  IoLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +
> +[Depex]
> +  TRUE
> +
> diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..88d47b9efb49f02dbadd0b6d76dac7a991df2124
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h
> @@ -0,0 +1,29 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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
> +  UINT8 Protocols[];

For paleontological reasons, EDK2 code does not allow arrays of
unspecified length at the end of a struct. I don't know which version
of which toolchain used to be the issue here, and I would be surprised
if anyone went through the trouble of writing that down, but it is the
reason that EDK2 only allows a [1] array, and hence care needs to be
taken to add/substract 1 as appropriate when sizing the variable.

So now, it's my turn to cut /you/ a deal here. If you stop whingeing
about frivolous patches that only move whitespace around or change //
for /*, or move ASSERT()s into if () conditions on cold-as-ice code
paths, I am not going to complain about the arrays of unspecified
length in this patch, simply because I don't take the coding standard
as gospel, and feel that the Tianocore could do with a bit more
pragmatism when it comes to matters like these.


> +} BASE_DISCOVER_LIST;
> +
> +#endif /* ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_ */
> diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..2807b6b476ac1b8cf821a29ca7a59a78e9188c52
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h
> @@ -0,0 +1,69 @@
> +/** @file
> +
> +  Copyright (c) 2017, ARM Limited. All rights reserved.
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD License
> +  which accompanies this distribution.  The full text of the license may be found at
> +  http://opensource.org/licenses/bsd-license.php
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +  System Control and Management Interface V1.0
> +    http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
> +    DEN0056A_System_Control_and_Management_Interface.pdf
> +**/
> +
> +#ifndef ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_
> +#define ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_
> +
> +#pragma pack(1)
> +
> +// Clock rate in two 32bit words.
> +typedef struct {
> +  UINT32 Low;
> +  UINT32 High;
> +} CLOCK_RATE_DWORD;
> +
> +// Format of the returned rate array. Linear or Non-linear,.RatesFlag Bit[12]
> +#define RATE_FORMAT_SHIFT           12
> +#define RATE_FORMAT_MASK            0x0001
> +#define RATE_FORMAT(RatesFlags)     ((RatesFlags >> RATE_FORMAT_SHIFT)  \
> +                                      & RATE_FORMAT_MASK)
> +
> +// Number of remaining rates after a call to the SCP, RatesFlag Bits[31:16]
> +#define NUM_REMAIN_RATES_SHIFT        16
> +#define NUM_REMAIN_RATES(RatesFlags)  ((RatesFlags >> NUM_REMAIN_RATES_SHIFT))
> +
> +// Number of rates that are returned by a call.to the SCP, RatesFlag Bits[11:0]
> +#define NUM_RATES_MASK              0x0FFF
> +#define NUM_RATES(RatesFlags)       (RatesFlags & NUM_RATES_MASK)
> +
> +// Return values for the CLOCK_DESCRIBER_RATE command.
> +typedef struct {
> +  UINT32 NumRatesFlags;
> +  CLOCK_RATE_DWORD Rates[];
> +} 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()
> +
> +#endif /* ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_ */
> diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..99fe80ae30bc818edef9125e5e8a2d11322feb41
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h
> @@ -0,0 +1,39 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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 <Drivers/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;
> +  SCMI_PERFORMANCE_LEVEL PerfLevel[]; // Offset to array of performance levels
> +} PERF_DESCRIBE_LEVELS;
> +
> +#endif /* ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ */
> diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..a2ce4bf9022cee79e0486db3cf9b4fdddf481081
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.h
> @@ -0,0 +1,41 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPrivate.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPrivate.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..ca3a712c1afd3e3bd25f831f57aab7e6bff1cddb
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPrivate.h
> @@ -0,0 +1,174 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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/ArmPlatformPkg/Include/Drivers/ArmScmi.h b/ArmPlatformPkg/Include/Drivers/ArmScmi.h

Please don't put stuff in Include/Drivers.

Things derived from industry specs belong in Include/IndustryStandard,
but given that this header only defines SCMI_MAX_STR_LEN, could you
move it into the protocol header instead?


> new file mode 100644
> index 0000000000000000000000000000000000000000..04ea3de5b34157ed459ee47440abbcaa7114e93a
> --- /dev/null
> +++ b/ArmPlatformPkg/Include/Drivers/ArmScmi.h
> @@ -0,0 +1,27 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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/ArmPlatformPkg/Include/Drivers/ArmScmiBaseProtocol.h b/ArmPlatformPkg/Include/Drivers/ArmScmiBaseProtocol.h

This belongs in Include/Protocol, and needs to be declared in the
package .dec file as well, along with its GUID.


> new file mode 100644
> index 0000000000000000000000000000000000000000..d8fab57fc354f14e79287520f6c8f05eb1eff141
> --- /dev/null
> +++ b/ArmPlatformPkg/Include/Drivers/ArmScmiBaseProtocol.h
> @@ -0,0 +1,182 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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 <Drivers/ArmScmi.h>
> +
> +#define BASE_PROTOCOL_VERSION  0x10000
> +
> +#define NUM_PROTOCOL_MASK      0xFFU
> +#define NUM_AGENT_MASK         0xFFU
> +
> +#define NUM_AGENT_SHIFT        0x8
> +
> +// Returns total protocols that are implemented (excluding the Base protocol)
> +#define SCMI_TOTAL_PROTOCOLS(Attr) (Attr & NUM_PROTOCOL_MASK)
> +
> +// Returns 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 } }
> +

Please wrap this line

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

This is not part of the protocol so it needs to be moved elsewhere.

> +#endif /* ARM_SCMI_BASE_PROTOCOL_H_ */
> +
> diff --git a/ArmPlatformPkg/Include/Drivers/ArmScmiClockProtocol.h b/ArmPlatformPkg/Include/Drivers/ArmScmiClockProtocol.h

Please move to Include/Protocol as well, and add declaration to the
package file.

> new file mode 100644
> index 0000000000000000000000000000000000000000..a97728e4dfe8efc3cd8dc29dc94987c1cc6c6a80
> --- /dev/null
> +++ b/ArmPlatformPkg/Include/Drivers/ArmScmiClockProtocol.h
> @@ -0,0 +1,225 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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 <Drivers/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 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;
> +
> +/** 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
> +  );
> +

Please move this into a separate header, it is not part of the protocol.

> +#endif /* ARM_SCMI_CLOCK_PROTOCOL_H_ */
> +
> diff --git a/ArmPlatformPkg/Include/Drivers/ArmScmiPerformanceProtocol.h b/ArmPlatformPkg/Include/Drivers/ArmScmiPerformanceProtocol.h

Same as above

> new file mode 100644
> index 0000000000000000000000000000000000000000..cb4aa6bf71df86cfd7a0dabb354112c5a38c978f
> --- /dev/null
> +++ b/ArmPlatformPkg/Include/Drivers/ArmScmiPerformanceProtocol.h
> @@ -0,0 +1,274 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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 <Drivers/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)
> +// Power values expressed in mW, 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;
> +
> +/** 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
> +  );
> +

Same as above

> +#endif /* ARM_SCMI_PERFORMANCE_PROTOCOL_H_ */
> +
> diff --git a/ArmPlatformPkg/Include/Library/ArmMtl.h b/ArmPlatformPkg/Include/Library/ArmMtl.h

Please rename to ArmMtlLib, and declare it as a library class in the
package file.

> new file mode 100644
> index 0000000000000000000000000000000000000000..9be65cfa0a1dcf0d984f29e5d95aedf5e0afac2b
> --- /dev/null
> +++ b/ArmPlatformPkg/Include/Library/ArmMtl.h
> @@ -0,0 +1,132 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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_MTL_H_
> +#define ARM_MTL_H_
> +
> +// Ideally we don't need packed struct. However we can't rely on compilers
> +#pragma pack(1)
> +
> +typedef struct {
> +  UINT32 Reserved1;
> +  UINT32 ChannelStatus;
> +  UINT64 Reserved2;
> +  UINT32 Flags;
> +  UINT32 Length;
> +  UINT32 MessageHeader;
> +  UINT32 Payload[];    // size less object gives offset to payload.
> +} MTL_MAILBOX;
> +
> +#pragma pack()
> +
> +// Channel Type, Low-priority, and High-priority
> +typedef enum {
> +  MTL_CHANNEL_TYPE_LOW = 0,
> +  MTL_CHANNEL_TYPE_HIGH = 1
> +} MTL_CHANNEL_TYPE;
> +
> +typedef struct {
> +  UINT64 PhysicalAddress;
> +  UINT32 ModifyMask;
> +  UINT32 PreserveMask;
> +} MTL_DOORBELL;
> +
> +typedef struct {
> +  MTL_CHANNEL_TYPE ChannelType;
> +  MTL_MAILBOX      * CONST MailBox;
> +  MTL_DOORBELL     DoorBell;
> +} MTL_CHANNEL;
> +
> +/** Wait until channel is free.
> +
> +  @param[in] Channel                Pointer to a channel.
> +  @param[in] TimeOutInMicroSeconds  Time out in micro seconds.
> +
> +  @retval EFI_SUCCESS               Channel is free.
> +  @retval EFI_TIMOUT                Timeout error.
> +**/
> +EFI_STATUS
> +MtlWaitUntilChannelFree (
> +  IN MTL_CHANNEL  *Channel,
> +  IN UINT64       TimeOutInMicroSeconds
> +  );
> +
> +/** Return the address of the message payload.
> +
> +  @param[in] Channel   Pointer to a channel.
> +
> +  @retval UINT32*      Pointer to the payload.
> +**/
> +UINT32*
> +MtlGetChannelPayload (
> +  IN MTL_CHANNEL  *Channel
> +  );
> +
> +/** Return pointer to a channel for the requested channel type.
> +
> +  @param[in] ChannelType        ChannelType, Low or High priority channel.
> +                                MTL_CHANNEL_TYPE_LOW or
> +                                MTL_CHANNEL_TYPE_HIGH
> +
> +  @param[out] Channel           Holds pointer to the channel.
> +
> +  @retval EFI_SUCCESS           Pointer to channel is returned.
> +  @retval EFI_UNSUPPORTED       Requested channel type not supported.
> +**/
> +EFI_STATUS
> +MtlGetChannel (
> +  IN  MTL_CHANNEL_TYPE  ChannelType,
> +  OUT MTL_CHANNEL       **Channel
> +  );
> +
> +
> +/** Mark the channel busy and ring the doorbell.
> +
> +  @param[in] Channel               Pointer to a channel.
> +  @param[in] MessageHeader         Message header.
> +
> +  @param[out] PayloadLength        Message length.
> +
> +  @retval EFI_SUCCESS              Message sent successfully.
> +  @retval EFI_DEVICE_ERROR         Channel is busy.
> +**/
> +EFI_STATUS
> +MtlSendMessage (
> +  IN  MTL_CHANNEL  *Channel,
> +  IN  UINT32       MessageHeader,
> +  OUT UINT32       PayloadLength
> +  );
> +
> +/** Wait for a response on a channel.
> +
> +  If channel is free after sending message, it implies SCP responded
> +  with a response on the channel.
> +
> +  @param[in] Channel               Pointer to a channel.
> +
> +  @retval EFI_SUCCESS              Message received successfully.
> +  @retval EFI_TIMOUT               Timeout error.
> +**/
> +EFI_STATUS
> +MtlReceiveMessage (
> +  IN  MTL_CHANNEL  *Channel,
> +  OUT UINT32       *MessageHeader,
> +  OUT UINT32       *PayloadLength
> +  );
> +
> +#endif  /* ARM_MTL_H_ */
> +
> diff --git a/ArmPlatformPkg/Drivers/ArmScmiDxe/Scmi.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/Scmi.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..8abbd90ce7bd5420cf81f89a4680e5563d7af085
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/Scmi.c
> @@ -0,0 +1,261 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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/ArmMtl.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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..144df459e9238b5e08c87ad12999a5491679d1fb
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c
> @@ -0,0 +1,320 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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 <Drivers/ArmScmiBaseProtocol.h>
> +
> +#include "ArmScmiBaseProtocolPrivate.h"
> +#include "ScmiPrivate.h"
> +
> +EFI_GUID gArmScmiBaseProtocolGuid = ARM_SCMI_BASE_PROTOCOL_GUID;
> +
> +/** 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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..895f3f6c5dccbd24e98ed73fa08c41a369d83f43
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c
> @@ -0,0 +1,419 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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 <Drivers/ArmScmiClockProtocol.h>
> +
> +#include "ArmScmiClockProtocolPrivate.h"
> +#include "ScmiPrivate.h"
> +
> +EFI_GUID gArmScmiClockProtocolGuid = ARM_SCMI_CLOCK_PROTOCOL_GUID;
> +

Please remove this, and declare the guid in the .inf file instead
(same applies to other protocols)


> +/** Convert to 64 bit value from two 32 bit words.
> +
> +  @param[in] Low   Lower 32 bits.
> +  @param[in] High  Higher 32 bits.
> +
> +  @retval UINT64   64 bit value.
> +**/
> +STATIC
> +UINT64
> +ConvertTo64Bit (
> +  IN UINT32 Low,
> +  IN UINT32 High
> +  )
> +{
> +   return (Low | ((UINT64)High << 32));
> +}
> +
> +/** Return version of the clock management protocol supported by SCP firmware.
> +
> +  @param[in]  This     A Pointer to SCMI_CLOCK_PROTOCOL Instance.
> +
> +  @param[out] Version  Version of the supported SCMI Clock management protocol.
> +
> +  @retval EFI_SUCCESS       The version is returned.
> +  @retval EFI_DEVICE_ERROR  SCP returns an SCMI error.
> +  @retval !(EFI_SUCCESS)    Other errors.
> +**/
> +STATIC
> +EFI_STATUS
> +ClockGetVersion (
> +  IN  SCMI_CLOCK_PROTOCOL  *This,
> +  OUT UINT32               *Version
> +  )
> +{
> +  return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_CLOCK, Version);
> +}
> +
> +/** Return total number of clock devices supported by the clock management
> +  protocol.
> +
> +  @param[in]  This         A Pointer to SCMI_CLOCK_PROTOCOL Instance.
> +
> +  @param[out] TotalClocks  Total number of clocks supported.
> +
> +  @retval EFI_SUCCESS       Total number of clocks supported is returned.
> +  @retval EFI_DEVICE_ERROR  SCP returns an SCMI error.
> +  @retval !(EFI_SUCCESS)    Other errors.
> +**/
> +STATIC
> +EFI_STATUS
> +ClockGetTotalClocks (
> +  IN  SCMI_CLOCK_PROTOCOL  *This,
> +  OUT UINT32               *TotalClocks
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT32     *ReturnValues;
> +
> +  Status = ScmiGetProtocolAttributes (SCMI_PROTOCOL_ID_CLOCK, &ReturnValues);
> +  if (EFI_ERROR (Status)) {
> +   return Status;
> +  }
> +
> +  *TotalClocks = SCMI_CLOCK_PROTOCOL_TOTAL_CLKS (ReturnValues[0]);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Return attributes of a clock device.
> +
> +  @param[in]  This        A Pointer to SCMI_CLOCK_PROTOCOL Instance.
> +  @param[in]  ClockId     Identifier for the clock device.
> +
> +  @param[out] Enabled         If TRUE, the clock device is enabled.
> +  @param[out] ClockAsciiName  A NULL terminated ASCII string with the clock
> +                              name, of up to 16 bytes.
> +
> +  @retval EFI_SUCCESS          Clock device attributes are returned.
> +  @retval EFI_DEVICE_ERROR     SCP returns an SCMI error.
> +  @retval !(EFI_SUCCESS)       Other errors.
> +**/
> +STATIC
> +EFI_STATUS
> +ClockGetClockAttributes (
> +  IN  SCMI_CLOCK_PROTOCOL  *This,
> +  IN  UINT32               ClockId,
> +  OUT BOOLEAN              *Enabled,
> +  OUT CHAR8                *ClockAsciiName
> +  )
> +{
> +  EFI_STATUS          Status;
> +
> +  UINT32              *MessageParams;
> +  CLOCK_ATTRIBUTES    *ClockAttributes;
> +  SCMI_COMMAND        Cmd;
> +  UINT32              PayloadLength;
> +
> +  Status = ScmiCommandGetPayload (&MessageParams);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  *MessageParams = ClockId;
> +
> +  Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK;
> +  Cmd.MessageId  = SCMI_MESSAGE_ID_CLOCK_ATTRIBUTES;
> +
> +  PayloadLength = sizeof (ClockId);
> +
> +  Status = ScmiCommandExecute (
> +             &Cmd,
> +             &PayloadLength,
> +             (UINT32**)&ClockAttributes
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +   // TRUE if bit 0 of ClockAttributes->Attributes is set.
> +  *Enabled = CLOCK_ENABLED (ClockAttributes->Attributes);
> +
> +  AsciiStrCpyS (
> +    ClockAsciiName,
> +    SCMI_MAX_STR_LEN,
> +    (CONST CHAR8*)ClockAttributes->ClockName
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Return list of rates supported by a given clock device.
> +
> +  @param[in] This        A pointer to SCMI_CLOCK_PROTOCOL Instance.
> +  @param[in] ClockId     Identifier for the clock device.
> +
> +  @param[out] Format      SCMI_CLOCK_RATE_FORMAT_DISCRETE: Clock device
> +                          supports range of clock rates which are non-linear.
> +
> +                          SCMI_CLOCK_RATE_FORMAT_LINEAR: Clock device supports
> +                          range of linear clock rates from Min to Max in steps.
> +
> +  @param[out] TotalRates  Total number of rates.
> +
> +  @param[in,out] RateArraySize  Size of the RateArray.
> +
> +  @param[out] RateArray   List of clock rates.
> +
> +  @retval EFI_SUCCESS          List of clock rates is returned.
> +  @retval EFI_DEVICE_ERROR     SCP returns an SCMI error.
> +  @retval EFI_BUFFER_TOO_SMALL RateArraySize is too small for the result.
> +                               It has been updated to the size needed.
> +  @retval !(EFI_SUCCESS)       Other errors.
> +**/
> +STATIC
> +EFI_STATUS
> +ClockDescribeRates (
> +  IN     SCMI_CLOCK_PROTOCOL     *This,
> +  IN     UINT32                   ClockId,
> +  OUT    SCMI_CLOCK_RATE_FORMAT  *Format,
> +  OUT    UINT32                  *TotalRates,
> +  IN OUT UINT32                  *RateArraySize,
> +  OUT    SCMI_CLOCK_RATE         *RateArray
> +  )
> +{
> +  EFI_STATUS             Status;
> +
> +  UINT32                 PayloadLength;
> +  SCMI_COMMAND           Cmd;
> +  UINT32                 *MessageParams;
> +  CLOCK_DESCRIBE_RATES   *DescribeRates;
> +  CLOCK_RATE_DWORD       *Rate;
> +
> +  UINT32                 RequiredArraySize = 0;
> +  UINT32                 RateIndex = 0;
> +  UINT32                 RateNo;
> +  UINT32                 RateOffset;
> +
> +  *TotalRates = 0;
> +
> +  Status = ScmiCommandGetPayload (&MessageParams);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK;
> +  Cmd.MessageId  = SCMI_MESSAGE_ID_CLOCK_DESCRIBE_RATES;
> +
> +  *MessageParams++  = ClockId;
> +
> +  do {
> +
> +    *MessageParams = RateIndex;
> +
> +    // Set Payload length, note PayloadLength is a IN/OUT parameter.
> +    PayloadLength  = sizeof (ClockId) + sizeof (RateIndex);
> +
> +    // Execute and wait for response on a SCMI channel.
> +    Status = ScmiCommandExecute (
> +               &Cmd,
> +               &PayloadLength,
> +               (UINT32**)&DescribeRates
> +               );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    if (*TotalRates == 0) {
> +      // In the first iteration we will get number of returned rates and number
> +      // of remaining rates. With this information calculate required size
> +      // for rate array. If provided RateArraySize is less, return an
> +      // error.
> +
> +      *Format = RATE_FORMAT (DescribeRates->NumRatesFlags);
> +
> +      *TotalRates = NUM_RATES (DescribeRates->NumRatesFlags)
> +                    + NUM_REMAIN_RATES (DescribeRates->NumRatesFlags);
> +
> +      if (*Format == SCMI_CLOCK_RATE_FORMAT_DISCRETE) {
> +         RequiredArraySize = (*TotalRates) * sizeof (UINT64);
> +      } else {
> +         // We need to return triplet of 64 bit value for each rate
> +         RequiredArraySize = (*TotalRates) * 3 * sizeof (UINT64);
> +      }
> +
> +      if (RequiredArraySize > (*RateArraySize)) {
> +        *RateArraySize = RequiredArraySize;
> +        return EFI_BUFFER_TOO_SMALL;
> +      }
> +    }
> +
> +    RateOffset = 0;
> +
> +    if (*Format == SCMI_CLOCK_RATE_FORMAT_DISCRETE) {
> +      for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) {
> +        Rate = &DescribeRates->Rates[RateOffset++];
> +        // Non-linear discrete rates.
> +        RateArray[RateIndex++].Rate = ConvertTo64Bit (Rate->Low, Rate->High);
> +      }
> +    } else {
> +      for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) {
> +        // Linear clock rates from minimum to maximum in steps
> +        // Minimum clock rate.
> +        Rate = &DescribeRates->Rates[RateOffset++];
> +        RateArray[RateIndex].Min = ConvertTo64Bit (Rate->Low, Rate->High);
> +
> +        Rate = &DescribeRates->Rates[RateOffset++];
> +        // Maximum clock rate.
> +        RateArray[RateIndex].Max = ConvertTo64Bit (Rate->Low, Rate->High);
> +
> +        Rate = &DescribeRates->Rates[RateOffset++];
> +        // Step.
> +        RateArray[RateIndex++].Step = ConvertTo64Bit (Rate->Low, Rate->High);
> +      }
> +    }
> +  } while (NUM_REMAIN_RATES (DescribeRates->NumRatesFlags) != 0);
> +
> +  // Update RateArraySize with RequiredArraySize.
> +  *RateArraySize = RequiredArraySize;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Get clock rate.
> +
> +  @param[in]  This        A Pointer to SCMI_CLOCK_PROTOCOL Instance.
> +  @param[in]  ClockId     Identifier for the clock device.
> +
> +  @param[out]  Rate       Clock rate.
> +
> +  @retval EFI_SUCCESS          Clock rate is returned.
> +  @retval EFI_DEVICE_ERROR     SCP returns an SCMI error.
> +  @retval !(EFI_SUCCESS)       Other errors.
> +**/
> +STATIC
> +EFI_STATUS
> +ClockRateGet (
> +  IN  SCMI_CLOCK_PROTOCOL  *This,
> +  IN  UINT32               ClockId,
> +  OUT UINT64               *Rate
> +  )
> +{
> +  EFI_STATUS     Status;
> +
> +  UINT32            *MessageParams;
> +  CLOCK_RATE_DWORD  *ClockRate;
> +  SCMI_COMMAND      Cmd;
> +
> +  UINT32         PayloadLength;
> +
> +  Status = ScmiCommandGetPayload (&MessageParams);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // Fill arguments for clock protocol command.
> +  *MessageParams  = ClockId;
> +
> +  Cmd.ProtocolId  = SCMI_PROTOCOL_ID_CLOCK;
> +  Cmd.MessageId   = SCMI_MESSAGE_ID_CLOCK_RATE_GET;
> +
> +  PayloadLength = sizeof (ClockId);
> +
> +  // Execute and wait for response on a SCMI channel.
> +  Status = ScmiCommandExecute (
> +             &Cmd,
> +             &PayloadLength,
> +             (UINT32**)&ClockRate
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  *Rate = ((UINT64)ClockRate->High << 32) | ClockRate->Low;
> +
> +  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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..b11d232d7e910f7ed0a165fb4e22e207c2c3e607
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiDxe.c
> @@ -0,0 +1,135 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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 <Drivers/ArmScmiBaseProtocol.h>
> +#include <Drivers/ArmScmiClockProtocol.h>
> +#include <Drivers/ArmScmiPerformanceProtocol.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +
> +#include "ScmiPrivate.h"
> +#include "ScmiDxe.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/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..3946dc21005430c430605bf60fb40fb99e2a0178
> --- /dev/null
> +++ b/ArmPlatformPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
> @@ -0,0 +1,457 @@
> +/** @file
> +
> +  Copyright (c) 2017, 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 <Drivers/ArmScmiPerformanceProtocol.h>
> +#include <string.h>
> +
> +#include "ArmScmiPerformanceProtocolPrivate.h"
> +#include "ScmiPrivate.h"
> +
> +EFI_GUID gArmScmiPerformanceProtocolGuid = ARM_SCMI_PERFORMANCE_PROTOCOL_GUID;
> +
> +/** 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 (
> +    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 (
> +    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;
> +
> +  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;
> +    }
> +
> +    if (RequiredSize == 0) {
> +      *NumLevels = NUM_PERF_LEVELS (Levels->NumLevels)
> +                   + NUM_REMAIN_PERF_LEVELS (Levels->NumLevels);
> +      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 < NUM_PERF_LEVELS (Levels->NumLevels);
> +         LevelNo++) {
> +       memcpy (
> +         &LevelArray[LevelIndex++],
> +         &Levels->PerfLevel[LevelNo],
> +         sizeof (SCMI_PERFORMANCE_LEVEL)
> +         );
> +    }
> +
> +  } while (NUM_REMAIN_PERF_LEVELS (Levels->NumLevels) != 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
> +                );
> +}
> --
> Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")
>
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel