From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4001:c06::242; helo=mail-io0-x242.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-io0-x242.google.com (mail-io0-x242.google.com [IPv6:2607:f8b0:4001:c06::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 84FBA2035B2C5 for ; Sat, 23 Dec 2017 06:00:52 -0800 (PST) Received: by mail-io0-x242.google.com with SMTP id t196so27201503iof.0 for ; Sat, 23 Dec 2017 06:05:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=VY6LL469ubU6z6xVLJpOcxoX3E/wG63tfjT2S9aCWMg=; b=f2uqfC68b/KMQZWkQ+IlhCsM4+5OUyEeP6gV5jl7X9MK3eeKK4ClHZYpOmzc97ltE7 z+cDoXV5sElvd6C+FnsLuTiPmRKiN3P2Bt35FnvyL96KVQq7LOtt59soDnIBHBiPpMWM FmoDzNiewv8CXHYShSDMgpJ06AHS0hTRYY7Wg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=VY6LL469ubU6z6xVLJpOcxoX3E/wG63tfjT2S9aCWMg=; b=O19KakWkTOYxSNgp5zQS1Ugkk2HXe67Ji1z0sfp9hoOpMvSR20nC0wmUusJTvjTJXm FS9KqQ7kAtpVocmk7PuDqwSMj+NZwisFVtbmILE9XSE5cxbKL5PupXc6Z0amLJb4Ec23 GeFo8o9O3hD90zpykxqjw0F1epq3WOYz+CTKw47Ug+ZiTRcduMTLTgUoJy0txBC5NS8w ezUIRG8YNPOFIH9MCoTEWXkMx+Fhyccqdy4jf//VzdpH7KL+f1Rcv4X5eMsrVY4fXCkY 215Enl6ZqlejM17sEs+3SyA9bCLbWOvKPyt5LjFuyHF5SJlFSCwgbIjbo6LRkpnb4w94 AaHg== X-Gm-Message-State: AKGB3mLKxo6GASXWgKHgqTSQgGHL+/NrUhlXWxAa9UXVoNcrwsokh8US H4+hrZcohKXumCoY1xZIj894sXe/u1mc9R6LsD1Ixw== X-Google-Smtp-Source: ACJfBouleqAuqaJNrSGpkZgwWHjUhP1AI8jWJcZGHeE36PGIwOGHbvu3WMmgISpHujU8TH1E4YZtm8i8pDGjPZHMkTI= X-Received: by 10.107.151.142 with SMTP id z136mr22858407iod.248.1514037939943; Sat, 23 Dec 2017 06:05:39 -0800 (PST) MIME-Version: 1.0 Received: by 10.107.52.14 with HTTP; Sat, 23 Dec 2017 06:05:39 -0800 (PST) In-Reply-To: <20171222183418.8616-14-evan.lloyd@arm.com> References: <20171222183418.8616-1-evan.lloyd@arm.com> <20171222183418.8616-14-evan.lloyd@arm.com> From: Ard Biesheuvel Date: Sat, 23 Dec 2017 14:05:39 +0000 Message-ID: To: Evan Lloyd Cc: "edk2-devel@lists.01.org" , <"ard.biesheuvel@linaro.org"@arm.com>, <"leif.lindholm@linaro.org"@arm.com>, <"Matteo.Carlini@arm.com"@arm.com>, <"nd@arm.com"@arm.com> Subject: Re: [PATCH v2 13/13] ArmPlatformPkg: Introduce SCMI protocol X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 23 Dec 2017 14:00:53 -0000 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable , couOn 22 December 2017 at 18:34, wrote: > From: Girish Pathak > > 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 > --- > 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/ArmPlatfo= rmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf > new file mode 100644 > index 0000000000000000000000000000000000000000..ad7c363c9d6621df36fb7bedd= ff9e2ae28127c52 > --- /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 ma= y 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 =3D 0x00010019 > + BASE_NAME =3D ArmScmiDxe > + FILE_GUID =3D 9585984C-F027-45E9-AFDF-ADAA6DFAAAC= 7 > + MODULE_TYPE =3D DXE_DRIVER > + VERSION_STRING =3D 1.0 > + ENTRY_POINT =3D 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..88d47b9efb49f02dbadd0b6d7= 6dac7a991df2124 > --- /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 I= MPLIED. > + > + 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 =3D 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/ArmScmiClockProtocolPrivat= e.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h > new file mode 100644 > index 0000000000000000000000000000000000000000..2807b6b476ac1b8cf821a29ca= 7a59a78e9188c52 > --- /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 I= MPLIED. > + > + 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 Bi= t[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_S= HIFT)) > + > +// Number of rates that are returned by a call.to the SCP, RatesFlag Bit= s[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) =3D= =3D 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/ArmScmiPerformanceProtocol= Private.h b/ArmPlatformPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPri= vate.h > new file mode 100644 > index 0000000000000000000000000000000000000000..99fe80ae30bc818edef9125e5= e8a2d11322feb41 > --- /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 I= MPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ > +#define ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ > + > +#include > + > +// Number of performance levels returned by a call to the SCP, Lvls Bits= [11:0] > +#define NUM_PERF_LEVELS_MASK 0x0FFF > +#define NUM_PERF_LEVELS(Lvls) (Lvls & NUM_PERF_LEVELS_MASK) > + > +// Number of performance levels remaining after a call to the SCP, Lvls = Bits[31:16] > +#define NUM_REMAIN_PERF_LEVELS_SHIFT 16 > +#define NUM_REMAIN_PERF_LEVELS(Lvls) (Lvls >> NUM_REMAIN_PERF_LEVELS_SHI= FT) > + > +/** Return values for SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS comman= d. > + SCMI Spec =C2=A7 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..a2ce4bf9022cee79e0486db3c= f9b4fdddf481081 > --- /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 I= MPLIED. > + > + 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/ArmPlatfor= mPkg/Drivers/ArmScmiDxe/ScmiPrivate.h > new file mode 100644 > index 0000000000000000000000000000000000000000..ca3a712c1afd3e3bd25f831f5= 7aab7e6bff1cddb > --- /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 I= MPLIED. > + > + 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 =3D 0x10, > + SCMI_PROTOCOL_ID_POWER_DOMAIN =3D 0x11, > + SCMI_PROTOCOL_ID_SYSTEM_POWER =3D 0x12, > + SCMI_PROTOCOL_ID_PERFORMANCE =3D 0x13, > + SCMI_PROTOCOL_ID_CLOCK =3D 0x14, > + SCMI_PROTOCOL_ID_SENSOR =3D 0x15 > +} SCMI_PROTOCOL_ID; > + > +// SCMI message types. > +typedef enum { > + SCMI_MESSAGE_TYPE_COMMAND =3D 0, > + SCMI_MESSAGE_TYPE_DELAYED_RESPONSE =3D 2, // Skipping 1 is deliberate. > + SCMI_MESSAGE_TYPE_NOTIFICATION =3D 3 > +} SCMI_MESSAGE_TYPE; > + > +// SCMI response error codes. > +typedef enum { > + SCMI_SUCCESS =3D 0, > + SCMI_NOT_SUPPORTED =3D -1, > + SCMI_INVALID_PARAMETERS =3D -2, > + SCMI_DENIED =3D -3, > + SCMI_NOT_FOUND =3D -4, > + SCMI_OUT_OF_RANGE =3D -5, > + SCMI_BUSY =3D -6, > + SCMI_COMMS_ERROR =3D -7, > + SCMI_GENERIC_ERROR =3D -8, > + SCMI_HARDWARE_ERROR =3D -9, > + SCMI_PROTOCOL_ERROR =3D -10 > +} SCMI_STATUS; > + > +// SCMI message IDs common to all protocols. > +typedef enum { > + SCMI_MESSAGE_ID_PROTOCOL_VERSION =3D 0x0, > + SCMI_MESSAGE_ID_PROTOCOL_ATTRIBUTES =3D 0x1, > + SCMI_MESSAGE_ID_PROTOCOL_MESSAGE_ATTRIBUTES =3D 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 poin= ter. > + @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 succes= sfully. > + @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 attr= ibutes. > + @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/In= clude/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..04ea3de5b34157ed459ee4744= 0abbcaa7114e93a > --- /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 I= MPLIED. > + > + 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/ArmPl= atformPkg/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..d8fab57fc354f14e79287520f= 6c8f05eb1eff141 > --- /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 I= MPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_BASE_PROTOCOL_H_ > +#define ARM_SCMI_BASE_PROTOCOL_H_ > + > +#include > + > +#define BASE_PROTOCOL_VERSION 0x10000 > + > +#define NUM_PROTOCOL_MASK 0xFFU > +#define NUM_AGENT_MASK 0xFFU > + > +#define NUM_AGENT_SHIFT 0x8 > + > +// Returns total protocols that are implemented (excluding the Base prot= ocol) > +#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_AGEN= T_MASK) > + > +#define ARM_SCMI_BASE_PROTOCOL_GUID { 0xd7e5abe9, 0x33ab, 0x418e, { 0x9= f, 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 retu= rned. > + @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 versi= on. > + > + @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 res= ult. > + 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 DiscoverImplementationVersi= on; > + SCMI_BASE_DISCOVER_LIST_PROTOCOLS DiscoverListProtocols; > +} SCMI_BASE_PROTOCOL; > + > +// SCMI Message IDs for Base protocol. > +typedef enum { > + SCMI_MESSAGE_ID_BASE_DISCOVER_VENDOR =3D 0x3, > + SCMI_MESSAGE_ID_BASE_DISCOVER_SUB_VENDOR =3D 0x4, > + SCMI_MESSAGE_ID_BASE_DISCOVER_IMPLEMENTATION_VERSION =3D 0x5, > + SCMI_MESSAGE_ID_BASE_DISCOVER_LIST_PROTOCOLS =3D 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/ArmP= latformPkg/Include/Drivers/ArmScmiClockProtocol.h Please move to Include/Protocol as well, and add declaration to the package file. > new file mode 100644 > index 0000000000000000000000000000000000000000..a97728e4dfe8efc3cd8dc29dc= 94987c1cc6c6a80 > --- /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 I= MPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_CLOCK_PROTOCOL_H_ > +#define ARM_SCMI_CLOCK_PROTOCOL_H_ > + > +#include > + > +#define ARM_SCMI_CLOCK_PROTOCOL_GUID { 0x91ce67a8, 0xe0aa, 0x4012, { 0xb= 9, 0x9f, 0xb6, 0xfc, 0xf3, 0x4, 0x8e, 0xaa } } > + > +extern EFI_GUID gArmScmiClockProtocolGuid; > + > +// Message Type for clock management protocol. > +typedef enum { > + SCMI_MESSAGE_ID_CLOCK_ATTRIBUTES =3D 0x3, > + SCMI_MESSAGE_ID_CLOCK_DESCRIBE_RATES =3D 0x4, > + SCMI_MESSAGE_ID_CLOCK_RATE_SET =3D 0x5, > + SCMI_MESSAGE_ID_CLOCK_RATE_GET =3D 0x6, > + SCMI_MESSAGE_ID_CLOCK_CONFIG_SET =3D 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_S= HIFT) \ > + && 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 devi= ce > + 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 fir= mware. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI Clock management pr= otocol. > + > + @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 manageme= nt > + 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 cl= ock > + 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-li= near. > + > + SCMI_CLOCK_RATE_FORMAT_LINEAR: Clock device su= pports > + 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 prot= ocol. > + > + @retval EFI_SUCCESS Clock protocol interface installed succ= essfully. > +**/ > +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..cb4aa6bf71df86cfd7a0dabb3= 54112c5a38c978f > --- /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 I= MPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_PERFORMANCE_PROTOCOL_H_ > +#define ARM_SCMI_PERFORMANCE_PROTOCOL_H_ > + > +#include > + > +#define PERFORMANCE_PROTOCOL_VERSION 0x10000 > + > +#define ARM_SCMI_PERFORMANCE_PROTOCOL_GUID { 0x9b8ba84, 0x3dd3, 0x49a6,= { 0xa0, 0x5a, 0x31, 0x34, 0xa5, 0xf0, 0x7b, 0xad } } > + > +extern EFI_GUID gArmScmiPerformanceProtocolGuid; > + > +typedef struct _SCMI_PERFORMANCE_PROTOCOL SCMI_PERFORMANCE_PROTOCOL; > + > +#pragma pack(1) > + > +#define POWER_IN_MW_SHIFT 16 > +#define POWER_IN_MW_MASK 0x1 > +#define NUM_PERF_DOMAINS_MASK 0xFFFF > + > +// Total number of performance domains, Attr Bits [15:0] > +#define SCMI_PERF_TOTAL_DOMAINS(Attr) (Attr & NUM_PERF_DOMAINS_MASK) > +// 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_LATEN= CY_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 S= CP. > + firmware. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI performance manage= ment > + 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 Instanc= e. > + > + @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 Instanc= e. > + @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 resul= t. > + 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 Instanc= e. > + @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 Instanc= e. > + @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 Instanc= e. > + @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 =3D 0x3, > + SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS =3D 0x4, > + SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET =3D 0x5, > + SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET =3D 0x6, > + SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET =3D 0x7, > + SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET =3D 0x8, > +} SCMI_MESSAGE_ID_PERFORMANCE; > + > +/** Initialize performance management protocol and install on a given Ha= ndle. > + > + @param[in] Handle Handle to install performance managemen= t > + protocol. > + > + @retval EFI_SUCCESS Performance protocol installed successf= ully. > +**/ > +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/Inc= lude/Library/ArmMtl.h Please rename to ArmMtlLib, and declare it as a library class in the package file. > new file mode 100644 > index 0000000000000000000000000000000000000000..9be65cfa0a1dcf0d984f29e5d= 95aedf5e0afac2b > --- /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 I= MPLIED. > + > + 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 compile= rs > +#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 =3D 0, > + MTL_CHANNEL_TYPE_HIGH =3D 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 channe= l. > + 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/Dr= ivers/ArmScmiDxe/Scmi.c > new file mode 100644 > index 0000000000000000000000000000000000000000..8abbd90ce7bd5420cf81f89a4= 680e5563d7af085 > --- /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 I= MPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#include > +#include > +#include > +#include > + > +#include "ScmiPrivate.h" > + > +// SCMI Specification 1.0 > +#define MAX_PROTOCOLS 6 > + > +#define PROTOCOL_MASK 0xF > + > +// Arbitrary timeout value 20ms. > +#define RESPONSE_TIMEOUT 20000 > + > +/** Return a pointer to the message payload. > + > + @param[out] Payload Holds pointer to the message payload. > + > + @retval EFI_SUCCESS Payload holds a valid message payload poin= ter. > + @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 =3D MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Payload will not be populated until channel is free. > + Status =3D MtlWaitUntilChannelFree (Channel, RESPONSE_TIMEOUT); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Get the address of the payload. > + *Payload =3D 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 succes= sfully. > + @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 !=3D NULL); > + > + Status =3D MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Fill in message header. > + MessageHeader =3D SCMI_MESSAGE_HEADER (Command->MessageId, > + SCMI_MESSAGE_TYPE_COMMAND, > + Command->ProtocolId > + ); > + > + // Send payload using MTL channel. > + Status =3D MtlSendMessage ( > + Channel, > + MessageHeader, > + *PayloadLength > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Wait for the response on the channel. > + Status =3D MtlReceiveMessage (Channel, &ResponseHeader, PayloadLength)= ; > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // SCMI must return MessageHeader unmodified. > + if (MessageHeader !=3D ResponseHeader) { > + ASSERT (FALSE); > + return EFI_DEVICE_ERROR; > + } > + > + Response =3D (SCMI_MESSAGE_RESPONSE*)MtlGetChannelPayload (Channel); > + > + if (Response->Status !=3D SCMI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "SCMI error: ProtocolId =3D 0x%x, MessageId =3D= 0x%x, error =3D %d\n", > + Command->ProtocolId, > + Command->MessageId, > + Response->Status > + )); > + > + ASSERT (FALSE); > + return EFI_DEVICE_ERROR; > + } > + > + if (ReturnValues !=3D NULL) { > + *ReturnValues =3D Response->ReturnValues; > + } > + > + return EFI_SUCCESS; > +} > + > +/** Internal common function useful for common protocol discovery messag= es. > + > + @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 =3D 0; > + > + Command.ProtocolId =3D ProtocolId; > + Command.MessageId =3D 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 =3D ScmiProtocolDiscoveryCommon ( > + ProtocolId, > + SCMI_MESSAGE_ID_PROTOCOL_VERSION, > + (UINT32**)&ProtocolVersion > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *Version =3D *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 attr= ibutes. > + @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/ArmPl= atformPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c > new file mode 100644 > index 0000000000000000000000000000000000000000..144df459e9238b5e08c87ad12= 999a5491679d1fb > --- /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 I= MPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#include > +#include > +#include > +#include > + > +#include "ArmScmiBaseProtocolPrivate.h" > +#include "ScmiPrivate.h" > + > +EFI_GUID gArmScmiBaseProtocolGuid =3D 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 retu= rned. > + @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 =3D ScmiGetProtocolAttributes (SCMI_PROTOCOL_ID_BASE, &ReturnVa= lues); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *TotalProtocols =3D 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 =3D SCMI_PROTOCOL_ID_BASE; > + Cmd.MessageId =3D MessageId; > + > + PayloadLength =3D 0; > + > + Status =3D 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 versi= on. > + > + @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 =3D SCMI_PROTOCOL_ID_BASE; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_BASE_DISCOVER_IMPLEMENTATION_VERSIO= N; > + > + PayloadLength =3D 0; > + > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + &ReturnValues > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *ImplementationVersion =3D 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 res= ult. > + 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 =3D BaseGetTotalProtocols (This, &TotalProtocols); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + RequiredSize =3D sizeof (UINT8) * TotalProtocols; > + if (*ProtocolListSize < RequiredSize) { > + *ProtocolListSize =3D RequiredSize; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_BASE; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_BASE_DISCOVER_LIST_PROTOCOLS; > + > + Skip =3D 0; > + > + while (Skip < TotalProtocols) { > + > + *MessageParams =3D Skip; > + > + // Note PayloadLength is a IN/OUT parameter. > + PayloadLength =3D sizeof (Skip); > + > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&DiscoverList > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + for (Index =3D 0; Index < DiscoverList->NumProtocols; Index++) { > + ProtocolList[Skip++] =3D DiscoverList->Protocols[Index]; > + } > + } > + > + *ProtocolListSize =3D RequiredSize; > + > + return EFI_SUCCESS; > +} > + > +// Instance of the SCMI Base protocol. > +STATIC CONST SCMI_BASE_PROTOCOL BaseProtocol =3D { > + 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/ArmP= latformPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c > new file mode 100644 > index 0000000000000000000000000000000000000000..895f3f6c5dccbd24e98ed73fa= 08c41a369d83f43 > --- /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 I= MPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > +#include > +#include > +#include > +#include > + > +#include "ArmScmiClockProtocolPrivate.h" > +#include "ScmiPrivate.h" > + > +EFI_GUID gArmScmiClockProtocolGuid =3D 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 fir= mware. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI Clock management pr= otocol. > + > + @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 manageme= nt > + 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 =3D ScmiGetProtocolAttributes (SCMI_PROTOCOL_ID_CLOCK, &ReturnV= alues); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *TotalClocks =3D 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 cl= ock > + 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 =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams =3D ClockId; > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_CLOCK; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_CLOCK_ATTRIBUTES; > + > + PayloadLength =3D sizeof (ClockId); > + > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&ClockAttributes > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + // TRUE if bit 0 of ClockAttributes->Attributes is set. > + *Enabled =3D 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-li= near. > + > + SCMI_CLOCK_RATE_FORMAT_LINEAR: Clock device su= pports > + 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 =3D 0; > + UINT32 RateIndex =3D 0; > + UINT32 RateNo; > + UINT32 RateOffset; > + > + *TotalRates =3D 0; > + > + Status =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_CLOCK; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_CLOCK_DESCRIBE_RATES; > + > + *MessageParams++ =3D ClockId; > + > + do { > + > + *MessageParams =3D RateIndex; > + > + // Set Payload length, note PayloadLength is a IN/OUT parameter. > + PayloadLength =3D sizeof (ClockId) + sizeof (RateIndex); > + > + // Execute and wait for response on a SCMI channel. > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&DescribeRates > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (*TotalRates =3D=3D 0) { > + // In the first iteration we will get number of returned rates and= number > + // of remaining rates. With this information calculate required si= ze > + // for rate array. If provided RateArraySize is less, return an > + // error. > + > + *Format =3D RATE_FORMAT (DescribeRates->NumRatesFlags); > + > + *TotalRates =3D NUM_RATES (DescribeRates->NumRatesFlags) > + + NUM_REMAIN_RATES (DescribeRates->NumRatesFlags); > + > + if (*Format =3D=3D SCMI_CLOCK_RATE_FORMAT_DISCRETE) { > + RequiredArraySize =3D (*TotalRates) * sizeof (UINT64); > + } else { > + // We need to return triplet of 64 bit value for each rate > + RequiredArraySize =3D (*TotalRates) * 3 * sizeof (UINT64); > + } > + > + if (RequiredArraySize > (*RateArraySize)) { > + *RateArraySize =3D RequiredArraySize; > + return EFI_BUFFER_TOO_SMALL; > + } > + } > + > + RateOffset =3D 0; > + > + if (*Format =3D=3D SCMI_CLOCK_RATE_FORMAT_DISCRETE) { > + for (RateNo =3D 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlag= s); RateNo++) { > + Rate =3D &DescribeRates->Rates[RateOffset++]; > + // Non-linear discrete rates. > + RateArray[RateIndex++].Rate =3D ConvertTo64Bit (Rate->Low, Rate-= >High); > + } > + } else { > + for (RateNo =3D 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlag= s); RateNo++) { > + // Linear clock rates from minimum to maximum in steps > + // Minimum clock rate. > + Rate =3D &DescribeRates->Rates[RateOffset++]; > + RateArray[RateIndex].Min =3D ConvertTo64Bit (Rate->Low, Rate->Hi= gh); > + > + Rate =3D &DescribeRates->Rates[RateOffset++]; > + // Maximum clock rate. > + RateArray[RateIndex].Max =3D ConvertTo64Bit (Rate->Low, Rate->Hi= gh); > + > + Rate =3D &DescribeRates->Rates[RateOffset++]; > + // Step. > + RateArray[RateIndex++].Step =3D ConvertTo64Bit (Rate->Low, Rate-= >High); > + } > + } > + } while (NUM_REMAIN_RATES (DescribeRates->NumRatesFlags) !=3D 0); > + > + // Update RateArraySize with RequiredArraySize. > + *RateArraySize =3D 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 =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Fill arguments for clock protocol command. > + *MessageParams =3D ClockId; > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_CLOCK; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_CLOCK_RATE_GET; > + > + PayloadLength =3D sizeof (ClockId); > + > + // Execute and wait for response on a SCMI channel. > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&ClockRate > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *Rate =3D ((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 =3D ScmiCommandGetPayload ((UINT32**)&ClockRateSetAttributes); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Fill arguments for clock protocol command. > + ClockRateSetAttributes->ClockId =3D ClockId; > + ClockRateSetAttributes->Flags =3D CLOCK_SET_DEFAULT_FLAGS; > + ClockRateSetAttributes->Rate.Low =3D (UINT32)Rate; > + ClockRateSetAttributes->Rate.High =3D (UINT32)(Rate >> 32); > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_CLOCK; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_CLOCK_RATE_SET; > + > + PayloadLength =3D sizeof (CLOCK_RATE_SET_ATTRIBUTES); > + > + // Execute and wait for response on a SCMI channel. > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + NULL > + ); > + > + return Status; > +} > + > +// Instance of the SCMI clock management protocol. > +STATIC CONST SCMI_CLOCK_PROTOCOL ScmiClockProtocol =3D { > + 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 prot= ocol. > + > + @retval EFI_SUCCESS Clock protocol interface installed succ= essfully. > +**/ > +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..b11d232d7e910f7ed0a165fb4= e22e207c2c3e607 > --- /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 I= MPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "ScmiPrivate.h" > +#include "ScmiDxe.h" > + > +STATIC CONST SCMI_PROTOCOL_INIT_TABLE ProtocolInitFxns[MAX_PROTOCOLS] = =3D { > + { 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 o= n > + the ImageHandle. > + > + @param[in] ImageHandle Handle to this EFI Image which will be used= to > + install Base, Clock and Performance protoco= ls. > + @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 support= ed. > + @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 =3D sizeof (SupportedList); > + > + ProtocolNo =3D SCMI_PROTOCOL_ID_BASE & PROTOCOL_ID_MASK; > + > + // Every SCMI implementation must implement the base protocol. > + Status =3D ProtocolInitFxns[ProtocolNo].Init (&ImageHandle); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + Status =3D gBS->LocateProtocol ( > + &gArmScmiBaseProtocolGuid, > + NULL, > + (VOID**)&BaseProtocol > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + // Get SCMI Base protocol version. > + Status =3D BaseProtocol->GetVersion (BaseProtocol, &Version); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + if (Version !=3D BASE_PROTOCOL_VERSION) { > + ASSERT (FALSE); > + return EFI_UNSUPPORTED; > + } > + > + // Apart from Base protocol, SCMI may implement various other protocol= s, > + // query total protocols implemented by the SCP firmware. > + NumProtocols =3D 0; > + Status =3D BaseProtocol->GetTotalProtocols (BaseProtocol, &NumProtocol= s); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + ASSERT (NumProtocols !=3D 0); > + > + // Get the list of protocols supported by SCP firmware on the platform= . > + Status =3D BaseProtocol->DiscoverListProtocols ( > + BaseProtocol, > + &SupportedListSize, > + SupportedList > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + // Install supported protocol on ImageHandle. > + for (Index =3D 0; Index < NumProtocols; Index++) { > + ProtocolNo =3D SupportedList[Index] & PROTOCOL_ID_MASK; > + if (ProtocolInitFxns[ProtocolNo].Init !=3D NULL) { > + Status =3D 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..3946dc21005430c430605bf60= fb40fb99e2a0178 > --- /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 I= MPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#include > +#include > +#include > + > +#include "ArmScmiPerformanceProtocolPrivate.h" > +#include "ScmiPrivate.h" > + > +EFI_GUID gArmScmiPerformanceProtocolGuid =3D ARM_SCMI_PERFORMANCE_PROTOC= OL_GUID; > + > +/** Return version of the performance management protocol supported by S= CP. > + firmware. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI performance manage= ment > + 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 Instanc= e. > + > + @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 =3D 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 Instanc= e. > + @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 =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams =3D DomainId; > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_PERFORMANCE_DOMAIN_ATTRIBUTES; > + > + PayloadLength =3D sizeof (DomainId); > + > + Status =3D 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 resul= t. > + 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 =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + LevelIndex =3D 0; > + RequiredSize =3D 0; > + > + *MessageParams++ =3D DomainId; > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS; > + > + do { > + > + *MessageParams =3D LevelIndex; > + > + // Note, PayloadLength is an IN/OUT parameter. > + PayloadLength =3D sizeof (DomainId) + sizeof (LevelIndex); > + > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&Levels > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (RequiredSize =3D=3D 0) { > + *NumLevels =3D NUM_PERF_LEVELS (Levels->NumLevels) > + + NUM_REMAIN_PERF_LEVELS (Levels->NumLevels); > + RequiredSize =3D (*NumLevels) * sizeof (SCMI_PERFORMANCE_LEVEL); > + > + if (RequiredSize > (*LevelArraySize)) { > + // Update LevelArraySize with required size. > + *LevelArraySize =3D RequiredSize; > + return EFI_BUFFER_TOO_SMALL; > + } > + } > + > + for (LevelNo =3D 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) !=3D 0); > + > + *LevelArraySize =3D 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 =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams++ =3D DomainId; > + *MessageParams++ =3D Limits->RangeMax; > + *MessageParams =3D Limits->RangeMin; > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET; > + > + PayloadLength =3D sizeof (DomainId) + sizeof (SCMI_PERFORMANCE_LIMITS)= ; > + > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + NULL > + ); > + > + return Status; > +} > + > +/** Get performance limits of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instanc= e. > + @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 =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams =3D DomainId; > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET; > + > + PayloadLength =3D sizeof (DomainId); > + > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&ReturnValues > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Limits->RangeMax =3D ReturnValues->RangeMax; > + Limits->RangeMin =3D ReturnValues->RangeMin; > + > + return EFI_SUCCESS; > +} > + > +/** Set performance level of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instanc= e. > + @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 =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams++ =3D DomainId; > + *MessageParams =3D Level; > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET; > + > + PayloadLength =3D sizeof (DomainId) + sizeof (Level); > + > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + NULL > + ); > + > + return Status; > +} > + > +/** Get performance level of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instanc= e. > + @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 =3D ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams =3D DomainId; > + > + Cmd.ProtocolId =3D SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId =3D SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET; > + > + PayloadLength =3D sizeof (DomainId); > + > + Status =3D ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + &ReturnValues > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *Level =3D *ReturnValues; > + > + return EFI_SUCCESS; > +} > + > +// Instance of the SCMI performance management protocol. > +STATIC CONST SCMI_PERFORMANCE_PROTOCOL PerformanceProtocol =3D { > + PerformanceGetVersion, > + PerformanceGetAttributes, > + PerformanceDomainAttributes, > + PerformanceDescribeLevels, > + PerformanceLimitsSet, > + PerformanceLimitsGet, > + PerformanceLevelSet, > + PerformanceLevelGet > +}; > + > +/** Initialize performance management protocol and install on a given Ha= ndle. > + > + @param[in] Handle Handle to install performance managemen= t > + protocol. > + > + @retval EFI_SUCCESS Performance protocol installed successf= ully. > +**/ > +EFI_STATUS > +ScmiPerformanceProtocolInit ( > + IN EFI_HANDLE* Handle > + ) > +{ > + return gBS->InstallMultipleProtocolInterfaces ( > + Handle, > + &gArmScmiPerformanceProtocolGuid, > + &PerformanceProtocol, > + NULL > + ); > +} > -- > Guid("CE165669-3EF3-493F-B85D-6190EE5B9759") >