From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2a00:1450:400c:c0c::242; helo=mail-wr0-x242.google.com; envelope-from=leif.lindholm@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-wr0-x242.google.com (mail-wr0-x242.google.com [IPv6:2a00:1450:400c:c0c::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 A97072277AF0D for ; Mon, 23 Apr 2018 04:31:58 -0700 (PDT) Received: by mail-wr0-x242.google.com with SMTP id c14-v6so152524wrd.4 for ; Mon, 23 Apr 2018 04:31:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=YjQ1vTpd7BMrZ7C0u7mE3DTOxjx6t2uwfQTpfoGd0UE=; b=MubEKT/koKsTst2o84YCQ1LF4KDXWVC+EBN4uuBrG50AVhNfqY/Ok5Ozob3ZnOdejX JsqoPYFhueS2Sr4kmDVkUiQ3Bun7UkR7WbHVp3YTHC2bAGSj/f2vxGmo9p1dFKBONESu W4cbxqsVgLpOBiY6F/Rk4EbeRNPARAHCCmc1U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=YjQ1vTpd7BMrZ7C0u7mE3DTOxjx6t2uwfQTpfoGd0UE=; b=XX+hQ4oRM01XAaePYxsGz6HuNYJq5+wISdvfsd1yCVMzioFMNZP87G0ukGYCp1WVfU L+w9Tv3dNv7+Ds0Y9VHRNftyWaRMH3XegF5j/EOpKWb2k6CxI5tNhkWQuJu/FzSi5CwB Vb8xtFNpz57V4jonivfNK8YjbjUw8jEgNlDr3QWzA83GwO/V8L0TwLaLXyWdFmK47xxY VaDWlNv88ENmW4Lhm/75eqi1LEDu1JaNCpa/3NNgWHMYmS5NKwLdDwGO75p7mj7MN8+Y cj7T2mwCJEr5aKprYpiBFpHrlJ4c+2ZA4nwYwzJtCd6ka0FvKu9jnz8K512buMuZizw+ ISHA== X-Gm-Message-State: ALQs6tDTsS+nTujHfHLOb6RogtaRpi9FMUAoSnnL707twkTmzIVuFsHS xy9fBrXOy5E9HEoIVXL1Wh53Iw== X-Google-Smtp-Source: AB8JxZpAXsDPnPRSVNOOO6UwzAtwxtUKY984QBK50isijhTLdFLbXdhvN51sfHwd4gCpSnP/0dvFXw== X-Received: by 10.28.109.80 with SMTP id i77mr8861908wmc.46.1524483114308; Mon, 23 Apr 2018 04:31:54 -0700 (PDT) Received: from bivouac.eciton.net (bivouac.eciton.net. [2a00:1098:0:86:1000:23:0:2]) by smtp.gmail.com with ESMTPSA id l15-v6sm11336776wrb.85.2018.04.23.04.31.52 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 23 Apr 2018 04:31:52 -0700 (PDT) Date: Mon, 23 Apr 2018 12:31:50 +0100 From: Leif Lindholm To: Girish Pathak Cc: edk2-devel@lists.01.org, ard.biesheuvel@linaro.org, Matteo.Carlini@arm.com, Stephanie.Hughes-Fitt@arm.com, nd@arm.com Message-ID: <20180423113150.6dgqzp23ersamcrh@bivouac.eciton.net> References: <20180320161212.79120-1-girish.pathak@arm.com> <20180320161212.79120-17-girish.pathak@arm.com> MIME-Version: 1.0 In-Reply-To: <20180320161212.79120-17-girish.pathak@arm.com> User-Agent: NeoMutt/20170113 (1.7.2) Subject: Re: [PATCH v3 16/16] ArmPkg: Introduce SCMI protocol X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Apr 2018 11:31:59 -0000 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hmm, I did find a few minor things below that I need to hear back on before pushing. On Tue, Mar 20, 2018 at 04:12:12PM +0000, Girish Pathak wrote: > This change introduces a new SCMI protocol driver for > Arm systems. The driver currently supports only clock > and performance management protocols. Other protocols > will be added as and when needed. > > Clock management protocol is used to configure various clocks > available on the platform e.g. HDLCD clock on the Juno platforms. > > Whereas performance management protocol allows adjustment > of various performance domains. Currently this is used to evaluate > performance of the Juno platform. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Girish Pathak > Signed-off-by: Evan Lloyd > --- > > Notes: > v3: > - Please rename ArmMtl.h to ArmMtlLibi.h, and > declare it as a library class in the package file. [Ard] > > Done, however ArmMtlLib.h is now part of earlier commit [Girish] > > - Move ArmScmiDxe to ArmPkg from ArmPlatformPkg [Ard] > > Done [Girish] > > - Declare gArmScmiBaseProtocolGuid and similar > protocols Guids in ArmPkg.dec [Ard] > > Done [Girish] > > - Replace flexible array member [] with [1] [Ard] > > Done [Girish] > > - Move protocol init function which are not part of > of protocol like ScmiBaseProtocolInit elsewhere [Ard] > > Done [Girish] > > - Please don't put stuff in Include/Drivers. [Ard] > > Moved headers to Include/Protocol. [Girish] > > ArmPkg/ArmPkg.dec | 13 + > ArmPkg/ArmPkg.dsc | 6 +- > ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h | 46 ++ > ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h | 84 ++++ > ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf | 53 +++ > ArmPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h | 55 +++ > ArmPkg/Drivers/ArmScmiDxe/Scmi.c | 262 +++++++++++ > ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c | 318 ++++++++++++++ > ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c | 418 ++++++++++++++++++ > ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c | 138 ++++++ > ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h | 41 ++ > ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c | 457 ++++++++++++++++++++ > ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h | 174 ++++++++ > ArmPkg/Include/Protocol/ArmScmi.h | 27 ++ > ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h | 174 ++++++++ > ArmPkg/Include/Protocol/ArmScmiClockProtocol.h | 218 ++++++++++ > ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h | 265 ++++++++++++ > 17 files changed, 2748 insertions(+), 1 deletion(-) > > diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec > index 881751d81c6384a3eb0b4c180c76d01a58266a74..16f7e40046429142b44b526043b61a3d5e089d2c 100644 > --- a/ArmPkg/ArmPkg.dec > +++ b/ArmPkg/ArmPkg.dec > @@ -51,6 +51,19 @@ [Guids.common] > > gArmGicDxeFileGuid = { 0xde371f7c, 0xdec4, 0x4d21, { 0xad, 0xf1, 0x59, 0x3a, 0xbc, 0xc1, 0x58, 0x82 } } > > +[Protocols.common] > + ## Arm System Control and Management Interface(SCMI) Base protocol > + ## ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h > + gArmScmiBaseProtocolGuid = { 0xd7e5abe9, 0x33ab, 0x418e, { 0x9f, 0x91, 0x72, 0xda, 0xe2, 0xba, 0x8e, 0x2f } } > + > + ## Arm System Control and Management Interface(SCMI) Clock management protocol > + ## ArmPkg/Include/Protocol/ArmScmiClockProtocol.h > + gArmScmiClockProtocolGuid = { 0x91ce67a8, 0xe0aa, 0x4012, { 0xb9, 0x9f, 0xb6, 0xfc, 0xf3, 0x4, 0x8e, 0xaa } } > + > + ## Arm System Control and Management Interface(SCMI) Clock management protocol > + ## ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h > + gArmScmiPerformanceProtocolGuid = { 0x9b8ba84, 0x3dd3, 0x49a6, { 0xa0, 0x5a, 0x31, 0x34, 0xa5, 0xf0, 0x7b, 0xad } } > + > [Ppis] > ## Include/Ppi/ArmMpCoreInfo.h > gArmMpCoreInfoPpiGuid = { 0x6847cc74, 0xe9ec, 0x4f8f, {0xa2, 0x9d, 0xab, 0x44, 0xe7, 0x54, 0xa8, 0xfc} } > diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc > index 526909458e0d80dbc5a65c8ad12ec1095dda48d2..22332090db7111e0668607a16288cefc1bace926 100644 > --- a/ArmPkg/ArmPkg.dsc > +++ b/ArmPkg/ArmPkg.dsc > @@ -2,7 +2,7 @@ > # ARM processor package. > # > # Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
> -# Copyright (c) 2011 - 2015, ARM Ltd. All rights reserved.
> +# Copyright (c) 2011 - 2018, ARM Ltd. All rights reserved.
> # Copyright (c) 2016, Linaro Ltd. All rights reserved.
> # > # This program and the accompanying materials > @@ -87,6 +87,8 @@ [LibraryClasses.common] > ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf > ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf > > + ArmMtlLib|ArmPkg/Library/ArmMtlNullLib/ArmMtlNullLib.inf > + > [LibraryClasses.common.PEIM] > HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf > PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf > @@ -144,5 +146,7 @@ [Components.common] > ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf > ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > > + ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf > + > [Components.AARCH64] > ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h > new file mode 100644 > index 0000000000000000000000000000000000000000..79c057d44128008ec276e3d58d8f1098c6a779b2 > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h > @@ -0,0 +1,46 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_ > +#define ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_ > + > +// Return values of BASE_DISCOVER_LIST_PROTOCOLS command. > +typedef struct { > + UINT32 NumProtocols; > + > + // Array of four protocols in each element > + // Total elements = 1 + (NumProtocols-1)/4 > + > + // NOTE: Since EDK2 does not allow flexible array member [] we declare > + // here array of 1 element length. However below is used as a variable > + // length array. > + UINT8 Protocols[1]; > +} BASE_DISCOVER_LIST; > + > +/** Initialize Base protocol and install protocol on a given handle. > + > + @param[in] Handle Handle to install Base protocol. > + > + @retval EFI_SUCCESS Base protocol interface installed > + successfully. > +**/ > +EFI_STATUS > +ScmiBaseProtocolInit ( > + IN OUT EFI_HANDLE* Handle > + ); > + > +#endif /* ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_ */ > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h > new file mode 100644 > index 0000000000000000000000000000000000000000..71245c16475d4d38d6dc66571b3fe3520c1cf1da > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h > @@ -0,0 +1,84 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_ > +#define ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_ > + > +#pragma pack(1) > + > +// Clock rate in two 32bit words. > +typedef struct { > + UINT32 Low; > + UINT32 High; > +} CLOCK_RATE_DWORD; > + > +// Format of the returned rate array. Linear or Non-linear,.RatesFlag Bit[12] > +#define RATE_FORMAT_SHIFT 12 > +#define RATE_FORMAT_MASK 0x0001 > +#define RATE_FORMAT(RatesFlags) ((RatesFlags >> RATE_FORMAT_SHIFT) \ > + & RATE_FORMAT_MASK) I'll decrease indentation of above line by one unless someone objects? > + > +// Number of remaining rates after a call to the SCP, RatesFlag Bits[31:16] > +#define NUM_REMAIN_RATES_SHIFT 16 > +#define NUM_REMAIN_RATES(RatesFlags) ((RatesFlags >> NUM_REMAIN_RATES_SHIFT)) > + > +// Number of rates that are returned by a call.to the SCP, RatesFlag Bits[11:0] > +#define NUM_RATES_MASK 0x0FFF > +#define NUM_RATES(RatesFlags) (RatesFlags & NUM_RATES_MASK) > + > +// Return values for the CLOCK_DESCRIBER_RATE command. > +typedef struct { > + UINT32 NumRatesFlags; > + > + // NOTE: Since EDK2 does not allow flexible array member [] we declare > + // here array of 1 element length. However below is used as a variable > + // length array. > + CLOCK_RATE_DWORD Rates[1]; > +} CLOCK_DESCRIBE_RATES; > + > +#define CLOCK_SET_DEFAULT_FLAGS 0 > + > +// Message parameters for CLOCK_RATE_SET command. > +typedef struct { > + UINT32 Flags; > + UINT32 ClockId; > + CLOCK_RATE_DWORD Rate; > +} CLOCK_RATE_SET_ATTRIBUTES; > + > +// if ClockAttr Bit[0] is set then clock device is enabled. > +#define CLOCK_ENABLE_MASK 0x1 > +#define CLOCK_ENABLED(ClockAttr) ((ClockAttr & CLOCK_ENABLE_MASK) == 1) > + > +typedef struct { > + UINT32 Attributes; > + UINT8 ClockName[SCMI_MAX_STR_LEN]; > +} CLOCK_ATTRIBUTES; > + > +#pragma pack() > + > +/** Initialize clock management protocol and install protocol on a given handle. > + > + @param[in] Handle Handle to install clock management protocol. > + > + @retval EFI_SUCCESS Clock protocol interface installed successfully. > +**/ > +EFI_STATUS > +ScmiClockProtocolInit ( > + IN EFI_HANDLE *Handle > + ); > + > +#endif /* ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_ */ > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf > new file mode 100644 > index 0000000000000000000000000000000000000000..05ce9c04ce468d74e5c6d38739f9056f3fc48694 > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf > @@ -0,0 +1,53 @@ > +#/** @file > +# > +# Copyright (c) 2017-2018, Arm Limited. All rights reserved. > +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the BSD License > +# which accompanies this distribution. The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +# > +# System Control and Management Interface V1.0 > +# http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > +# DEN0056A_System_Control_and_Management_Interface.pdf > +#**/ > + > +[Defines] > + INF_VERSION = 0x00010019 > + BASE_NAME = ArmScmiDxe > + FILE_GUID = 9585984C-F027-45E9-AFDF-ADAA6DFAAAC7 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = ArmScmiDxeEntryPoint > + > +[Sources.common] > + Scmi.c > + ScmiBaseProtocol.c > + ScmiClockProtocol.c > + ScmiDxe.c > + ScmiPerformanceProtocol.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + ArmPlatformPkg/ArmPlatformPkg.dec > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + ArmLib > + ArmMtlLib > + DebugLib > + IoLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + > +[Protocols] > + gArmScmiBaseProtocolGuid > + gArmScmiClockProtocolGuid > + gArmScmiPerformanceProtocolGuid > + > +[Depex] > + TRUE > + > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h > new file mode 100644 > index 0000000000000000000000000000000000000000..4514f45a9f5dd960d2844a19b57a91b93149f1b9 > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ArmScmiPerformanceProtocolPrivate.h > @@ -0,0 +1,55 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ > +#define ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ > + > +#include > + > +// Number of performance levels returned by a call to the SCP, Lvls Bits[11:0] > +#define NUM_PERF_LEVELS_MASK 0x0FFF > +#define NUM_PERF_LEVELS(Lvls) (Lvls & NUM_PERF_LEVELS_MASK) > + > +// Number of performance levels remaining after a call to the SCP, Lvls Bits[31:16] > +#define NUM_REMAIN_PERF_LEVELS_SHIFT 16 > +#define NUM_REMAIN_PERF_LEVELS(Lvls) (Lvls >> NUM_REMAIN_PERF_LEVELS_SHIFT) > + > +/** Return values for SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS command. > + SCMI Spec ? 4.5.2.5 > +**/ > +typedef struct { > + UINT32 NumLevels; > + > + // NOTE: Since EDK2 does not allow flexible array member [] we declare > + // here array of 1 element length. However below is used as a variable > + // length array. > + SCMI_PERFORMANCE_LEVEL PerfLevel[1]; // Offset to array of performance levels > +} PERF_DESCRIBE_LEVELS; > + > +/** Initialize performance management protocol and install on a given Handle. > + > + @param[in] Handle Handle to install performance management > + protocol. > + > + @retval EFI_SUCCESS Performance protocol installed successfully. > +**/ > +EFI_STATUS > +ScmiPerformanceProtocolInit ( > + IN EFI_HANDLE* Handle > + ); > + > +#endif /* ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ */ > diff --git a/ArmPkg/Drivers/ArmScmiDxe/Scmi.c b/ArmPkg/Drivers/ArmScmiDxe/Scmi.c > new file mode 100644 > index 0000000000000000000000000000000000000000..1e279f69cf615428dbb6477b8ac7de3258628df3 > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/Scmi.c > @@ -0,0 +1,262 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#include > +#include > +#include > +#include > + > +#include "ScmiPrivate.h" > + > +// SCMI Specification 1.0 > +#define MAX_PROTOCOLS 6 > + > +#define PROTOCOL_MASK 0xF > + > +// Arbitrary timeout value 20ms. > +#define RESPONSE_TIMEOUT 20000 > + > +/** Return a pointer to the message payload. > + > + @param[out] Payload Holds pointer to the message payload. > + > + @retval EFI_SUCCESS Payload holds a valid message payload pointer. > + @retval EFI_TIMEOUT Time out error if MTL channel is busy. > + @retval EFI_UNSUPPORTED If MTL channel is unsupported. > +**/ > +EFI_STATUS > +ScmiCommandGetPayload ( > + OUT UINT32** Payload > + ) > +{ > + EFI_STATUS Status; > + MTL_CHANNEL *Channel; > + > + // Get handle to the Channel. > + Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Payload will not be populated until channel is free. > + Status = MtlWaitUntilChannelFree (Channel, RESPONSE_TIMEOUT); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Get the address of the payload. > + *Payload = MtlGetChannelPayload (Channel); > + > + return EFI_SUCCESS; > +} > + > +/** Execute a SCMI command and receive a response. > + > + This function uses a MTL channel to transfer message to SCP > + and waits for a response. > + > + @param[in] Command Pointer to the SCMI command (Protocol ID > + and Message ID) > + > + @param[in,out] PayloadLength SCMI command message length. > + > + @param[out] OPTIONAL ReturnValues Pointer to SCMI response. > + > + @retval OUT EFI_SUCCESS Command sent and message received successfully. > + @retval OUT EFI_UNSUPPORTED Channel not supported. > + @retval OUT EFI_TIMEOUT Timeout on the channel. > + @retval OUT EFI_DEVICE_ERROR Channel not ready. > + @retval OUT EFI_DEVICE_ERROR Message Header corrupted. > + @retval OUT EFI_DEVICE_ERROR SCMI error. > +**/ > +EFI_STATUS > +ScmiCommandExecute ( > + IN SCMI_COMMAND *Command, > + IN OUT UINT32 *PayloadLength, > + OUT UINT32 **ReturnValues OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + SCMI_MESSAGE_RESPONSE *Response; > + UINT32 MessageHeader; > + UINT32 ResponseHeader; > + MTL_CHANNEL *Channel; > + > + ASSERT (PayloadLength != NULL); > + > + Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Fill in message header. > + MessageHeader = SCMI_MESSAGE_HEADER ( > + Command->MessageId, > + SCMI_MESSAGE_TYPE_COMMAND, > + Command->ProtocolId > + ); > + > + // Send payload using MTL channel. > + Status = MtlSendMessage ( > + Channel, > + MessageHeader, > + *PayloadLength > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Wait for the response on the channel. > + Status = MtlReceiveMessage (Channel, &ResponseHeader, PayloadLength); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // SCMI must return MessageHeader unmodified. > + if (MessageHeader != ResponseHeader) { > + ASSERT (FALSE); > + return EFI_DEVICE_ERROR; > + } > + > + Response = (SCMI_MESSAGE_RESPONSE*)MtlGetChannelPayload (Channel); > + > + if (Response->Status != SCMI_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "SCMI error: ProtocolId = 0x%x, MessageId = 0x%x, error = %d\n", > + Command->ProtocolId, > + Command->MessageId, > + Response->Status > + )); > + > + ASSERT (FALSE); > + return EFI_DEVICE_ERROR; > + } > + > + if (ReturnValues != NULL) { > + *ReturnValues = Response->ReturnValues; > + } > + > + return EFI_SUCCESS; > +} > + > +/** Internal common function useful for common protocol discovery messages. > + > + @param[in] ProtocolId Protocol Id of the the protocol. > + @param[in] MesaageId Message Id of the message. > + > + @param[out] ReturnValues SCMI response return values. > + > + @retval EFI_SUCCESS Success with valid return values. > + @retval EFI_DEVICE_ERROR SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +ScmiProtocolDiscoveryCommon ( > + IN SCMI_PROTOCOL_ID ProtocolId, > + IN SCMI_MESSAGE_ID MessageId, > + OUT UINT32 **ReturnValues > + ) > +{ > + SCMI_COMMAND Command; > + UINT32 PayloadLength = 0; > + > + Command.ProtocolId = ProtocolId; > + Command.MessageId = MessageId; > + > + return ScmiCommandExecute ( > + &Command, > + &PayloadLength, > + ReturnValues > + ); > +} > + > +/** Return protocol version from SCP for a given protocol ID. > + > + @param[in] Protocol ID Protocol ID. > + @param[out] Version Pointer to version of the protocol. > + > + @retval EFI_SUCCESS Version holds a valid version received > + from the SCP. > + @retval EFI_DEVICE_ERROR SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +ScmiGetProtocolVersion ( > + IN SCMI_PROTOCOL_ID ProtocolId, > + OUT UINT32 *Version > + ) > +{ > + EFI_STATUS Status; > + UINT32 *ProtocolVersion; > + > + Status = ScmiProtocolDiscoveryCommon ( > + ProtocolId, > + SCMI_MESSAGE_ID_PROTOCOL_VERSION, > + (UINT32**)&ProtocolVersion > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *Version = *ProtocolVersion; > + > + return EFI_SUCCESS; > +} > + > +/** Return protocol attributes from SCP for a given protocol ID. > + > + @param[in] Protocol ID Protocol ID. > + @param[out] ReturnValues Pointer to attributes of the protocol. > + > + @retval EFI_SUCCESS ReturnValues points to protocol attributes. > + @retval EFI_DEVICE_ERROR SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +ScmiGetProtocolAttributes ( > + IN SCMI_PROTOCOL_ID ProtocolId, > + OUT UINT32 **ReturnValues > + ) > +{ > + return ScmiProtocolDiscoveryCommon ( > + ProtocolId, > + SCMI_MESSAGE_ID_PROTOCOL_ATTRIBUTES, > + ReturnValues > + ); > +} > + > +/** Return protocol message attributes from SCP for a given protocol ID. > + > + @param[in] Protocol ID Protocol ID. > + @param[out] Attributes Pointer to attributes of the protocol. > + > + @retval EFI_SUCCESS ReturnValues points to protocol message attributes. > + @retval EFI_DEVICE_ERROR SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +ScmiGetProtocolMessageAttributes ( > + IN SCMI_PROTOCOL_ID ProtocolId, > + OUT UINT32 **ReturnValues > + ) > +{ > + return ScmiProtocolDiscoveryCommon ( > + ProtocolId, > + SCMI_MESSAGE_ID_PROTOCOL_MESSAGE_ATTRIBUTES, > + ReturnValues > + ); > +} > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c > new file mode 100644 > index 0000000000000000000000000000000000000000..0829438c82ec5723cfbbf9c411d10fcf22a22d89 > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c > @@ -0,0 +1,318 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#include > +#include > +#include > +#include > + > +#include "ArmScmiBaseProtocolPrivate.h" > +#include "ScmiPrivate.h" > + > +/** Return version of the Base protocol supported by SCP firmware. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI Base protocol. > + > + @retval EFI_SUCCESS The version of the protocol is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +BaseGetVersion ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT32 *Version > + ) > +{ > + return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_BASE, Version); > +} > + > +/** Return total number of SCMI protocols supported by the SCP firmware. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] TotalProtocols Total number of SCMI protocols supported. > + > + @retval EFI_SUCCESS Total number of protocols supported are returned. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +BaseGetTotalProtocols ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT32 *TotalProtocols > + ) > +{ > + EFI_STATUS Status; > + UINT32 *ReturnValues; > + > + Status = ScmiGetProtocolAttributes (SCMI_PROTOCOL_ID_BASE, &ReturnValues); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *TotalProtocols = SCMI_TOTAL_PROTOCOLS (ReturnValues[0]); > + > + return EFI_SUCCESS; > +} > + > +/** Common function which returns vendor details. > + > + @param[in] MessageId SCMI_MESSAGE_ID_BASE_DISCOVER_VENDOR > + OR > + SCMI_MESSAGE_ID_BASE_DISCOVER_SUB_VENDOR > + > + @param[out] VendorIdentifier ASCII name of the vendor/subvendor. > + > + @retval EFI_SUCCESS VendorIdentifier is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +BaseDiscoverVendorDetails ( > + IN SCMI_MESSAGE_ID_BASE MessageId, > + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] > + ) > +{ > + EFI_STATUS Status; > + UINT32 *ReturnValues; > + SCMI_COMMAND Cmd; > + UINT32 PayloadLength; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_BASE; > + Cmd.MessageId = MessageId; > + > + PayloadLength = 0; > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + &ReturnValues > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + AsciiStrCpyS ( > + (CHAR8*)VendorIdentifier, > + SCMI_MAX_STR_LEN, > + (CONST CHAR8*)ReturnValues > + ); > + > + return EFI_SUCCESS; > +} > + > +/** Return vendor name. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] VendorIdentifier Null terminated ASCII string of up to > + 16 bytes with a vendor name. > + > + @retval EFI_SUCCESS VendorIdentifier is returned. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +BaseDiscoverVendor ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] > + ) > +{ > + return BaseDiscoverVendorDetails ( > + SCMI_MESSAGE_ID_BASE_DISCOVER_VENDOR, > + VendorIdentifier > + ); > +} > + > +/** Return sub vendor name. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] VendorIdentifier Null terminated ASCII string of up to > + 16 bytes with a sub vendor name. > + > + @retval EFI_SUCCESS VendorIdentifier is returned. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +BaseDiscoverSubVendor ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] > + ) > +{ > + return BaseDiscoverVendorDetails ( > + SCMI_MESSAGE_ID_BASE_DISCOVER_SUB_VENDOR, > + VendorIdentifier > + ); > +} > + > +/** Return implementation version. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] ImplementationVersion Vendor specific implementation version. > + > + @retval EFI_SUCCESS Implementation version is returned. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +BaseDiscoverImplVersion ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT32 *ImplementationVersion > + ) > +{ > + EFI_STATUS Status; > + UINT32 *ReturnValues; > + SCMI_COMMAND Cmd; > + UINT32 PayloadLength; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_BASE; > + Cmd.MessageId = SCMI_MESSAGE_ID_BASE_DISCOVER_IMPLEMENTATION_VERSION; > + > + PayloadLength = 0; > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + &ReturnValues > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *ImplementationVersion = ReturnValues[0]; > + > + return EFI_SUCCESS; > +} > + > +/** Return list of protocols. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] ProtocolListSize Size of the ProtocolList. > + > + @param[out] ProtocolList Protocol list. > + > + @retval EFI_SUCCESS List of protocols is returned. > + @retval EFI_BUFFER_TOO_SMALL ProtocolListSize is too small for the result. > + It has been updated to the size needed. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +BaseDiscoverListProtocols ( > + IN SCMI_BASE_PROTOCOL *This, > + IN OUT UINT32 *ProtocolListSize, > + OUT UINT8 *ProtocolList > + ) > +{ > + EFI_STATUS Status; > + UINT32 TotalProtocols; > + UINT32 *MessageParams; > + BASE_DISCOVER_LIST *DiscoverList; > + UINT32 Skip; > + UINT32 Index; > + SCMI_COMMAND Cmd; > + UINT32 PayloadLength; > + UINT32 RequiredSize; > + > + Status = BaseGetTotalProtocols (This, &TotalProtocols); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + RequiredSize = sizeof (UINT8) * TotalProtocols; > + if (*ProtocolListSize < RequiredSize) { > + *ProtocolListSize = RequiredSize; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_BASE; > + Cmd.MessageId = SCMI_MESSAGE_ID_BASE_DISCOVER_LIST_PROTOCOLS; > + > + Skip = 0; > + > + while (Skip < TotalProtocols) { > + > + *MessageParams = Skip; > + > + // Note PayloadLength is a IN/OUT parameter. > + PayloadLength = sizeof (Skip); > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&DiscoverList > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + for (Index = 0; Index < DiscoverList->NumProtocols; Index++) { > + ProtocolList[Skip++] = DiscoverList->Protocols[Index]; > + } > + } > + > + *ProtocolListSize = RequiredSize; > + > + return EFI_SUCCESS; > +} > + > +// Instance of the SCMI Base protocol. > +STATIC CONST SCMI_BASE_PROTOCOL BaseProtocol = { > + BaseGetVersion, > + BaseGetTotalProtocols, > + BaseDiscoverVendor, > + BaseDiscoverSubVendor, > + BaseDiscoverImplVersion, > + BaseDiscoverListProtocols > +}; > + > +/** Initialize Base protocol and install protocol on a given handle. > + > + @param[in] Handle Handle to install Base protocol. > + > + @retval EFI_SUCCESS Base protocol interface installed > + successfully. > +**/ > +EFI_STATUS > +ScmiBaseProtocolInit ( > + IN OUT EFI_HANDLE* Handle > + ) > +{ > + return gBS->InstallMultipleProtocolInterfaces ( > + Handle, > + &gArmScmiBaseProtocolGuid, > + &BaseProtocol, > + NULL > + ); > +} > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c > new file mode 100644 > index 0000000000000000000000000000000000000000..fe7edd2a8c8b7761fb3008e66d192ef1ee1ade2e > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c > @@ -0,0 +1,418 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#include > +#include > +#include > +#include > + > +#include "ArmScmiClockProtocolPrivate.h" > +#include "ScmiPrivate.h" > + > +/** Convert to 64 bit value from two 32 bit words. > + > + @param[in] Low Lower 32 bits. > + @param[in] High Higher 32 bits. > + > + @retval UINT64 64 bit value. > +**/ > +STATIC > +UINT64 > +ConvertTo64Bit ( > + IN UINT32 Low, > + IN UINT32 High > + ) > +{ > + return (Low | ((UINT64)High << 32)); > +} Suggestion for future improvement: make this a macro in Base.h The SIGNATURE_64 macro in there would already benefit from it. > + > +/** Return version of the clock management protocol supported by SCP firmware. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI Clock management protocol. > + > + @retval EFI_SUCCESS The version is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +ClockGetVersion ( > + IN SCMI_CLOCK_PROTOCOL *This, > + OUT UINT32 *Version > + ) > +{ > + return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_CLOCK, Version); > +} > + > +/** Return total number of clock devices supported by the clock management > + protocol. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + > + @param[out] TotalClocks Total number of clocks supported. > + > + @retval EFI_SUCCESS Total number of clocks supported is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +ClockGetTotalClocks ( > + IN SCMI_CLOCK_PROTOCOL *This, > + OUT UINT32 *TotalClocks > + ) > +{ > + EFI_STATUS Status; > + UINT32 *ReturnValues; > + > + Status = ScmiGetProtocolAttributes (SCMI_PROTOCOL_ID_CLOCK, &ReturnValues); > + if (EFI_ERROR (Status)) { > + return Status; Missing space (will add before committing). > + } > + > + *TotalClocks = SCMI_CLOCK_PROTOCOL_TOTAL_CLKS (ReturnValues[0]); > + > + return EFI_SUCCESS; > +} > + > +/** Return attributes of a clock device. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + @param[in] ClockId Identifier for the clock device. > + > + @param[out] Enabled If TRUE, the clock device is enabled. > + @param[out] ClockAsciiName A NULL terminated ASCII string with the clock > + name, of up to 16 bytes. > + > + @retval EFI_SUCCESS Clock device attributes are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +ClockGetClockAttributes ( > + IN SCMI_CLOCK_PROTOCOL *This, > + IN UINT32 ClockId, > + OUT BOOLEAN *Enabled, > + OUT CHAR8 *ClockAsciiName > + ) > +{ > + EFI_STATUS Status; > + > + UINT32 *MessageParams; > + CLOCK_ATTRIBUTES *ClockAttributes; > + SCMI_COMMAND Cmd; > + UINT32 PayloadLength; > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams = ClockId; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK; > + Cmd.MessageId = SCMI_MESSAGE_ID_CLOCK_ATTRIBUTES; > + > + PayloadLength = sizeof (ClockId); > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&ClockAttributes > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + // TRUE if bit 0 of ClockAttributes->Attributes is set. > + *Enabled = CLOCK_ENABLED (ClockAttributes->Attributes); > + > + AsciiStrCpyS ( > + ClockAsciiName, > + SCMI_MAX_STR_LEN, > + (CONST CHAR8*)ClockAttributes->ClockName > + ); > + > + return EFI_SUCCESS; > +} > + > +/** Return list of rates supported by a given clock device. > + > + @param[in] This A pointer to SCMI_CLOCK_PROTOCOL Instance. > + @param[in] ClockId Identifier for the clock device. > + > + @param[out] Format SCMI_CLOCK_RATE_FORMAT_DISCRETE: Clock device > + supports range of clock rates which are non-linear. > + > + SCMI_CLOCK_RATE_FORMAT_LINEAR: Clock device supports > + range of linear clock rates from Min to Max in steps. > + > + @param[out] TotalRates Total number of rates. > + > + @param[in,out] RateArraySize Size of the RateArray. > + > + @param[out] RateArray List of clock rates. > + > + @retval EFI_SUCCESS List of clock rates is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval EFI_BUFFER_TOO_SMALL RateArraySize is too small for the result. > + It has been updated to the size needed. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +ClockDescribeRates ( > + IN SCMI_CLOCK_PROTOCOL *This, > + IN UINT32 ClockId, > + OUT SCMI_CLOCK_RATE_FORMAT *Format, > + OUT UINT32 *TotalRates, > + IN OUT UINT32 *RateArraySize, > + OUT SCMI_CLOCK_RATE *RateArray > + ) > +{ > + EFI_STATUS Status; > + > + UINT32 PayloadLength; > + SCMI_COMMAND Cmd; > + UINT32 *MessageParams; > + CLOCK_DESCRIBE_RATES *DescribeRates; > + CLOCK_RATE_DWORD *Rate; > + > + UINT32 RequiredArraySize = 0; > + UINT32 RateIndex = 0; > + UINT32 RateNo; > + UINT32 RateOffset; > + > + *TotalRates = 0; > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK; > + Cmd.MessageId = SCMI_MESSAGE_ID_CLOCK_DESCRIBE_RATES; > + > + *MessageParams++ = ClockId; > + > + do { > + > + *MessageParams = RateIndex; > + > + // Set Payload length, note PayloadLength is a IN/OUT parameter. > + PayloadLength = sizeof (ClockId) + sizeof (RateIndex); > + > + // Execute and wait for response on a SCMI channel. > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&DescribeRates > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (*TotalRates == 0) { > + // In the first iteration we will get number of returned rates and number > + // of remaining rates. With this information calculate required size > + // for rate array. If provided RateArraySize is less, return an > + // error. > + > + *Format = RATE_FORMAT (DescribeRates->NumRatesFlags); > + > + *TotalRates = NUM_RATES (DescribeRates->NumRatesFlags) > + + NUM_REMAIN_RATES (DescribeRates->NumRatesFlags); > + > + if (*Format == SCMI_CLOCK_RATE_FORMAT_DISCRETE) { > + RequiredArraySize = (*TotalRates) * sizeof (UINT64); > + } else { > + // We need to return triplet of 64 bit value for each rate > + RequiredArraySize = (*TotalRates) * 3 * sizeof (UINT64); > + } > + > + if (RequiredArraySize > (*RateArraySize)) { > + *RateArraySize = RequiredArraySize; > + return EFI_BUFFER_TOO_SMALL; > + } > + } > + > + RateOffset = 0; > + > + if (*Format == SCMI_CLOCK_RATE_FORMAT_DISCRETE) { > + for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) { > + Rate = &DescribeRates->Rates[RateOffset++]; > + // Non-linear discrete rates. > + RateArray[RateIndex++].Rate = ConvertTo64Bit (Rate->Low, Rate->High); > + } > + } else { > + for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) { > + // Linear clock rates from minimum to maximum in steps > + // Minimum clock rate. > + Rate = &DescribeRates->Rates[RateOffset++]; > + RateArray[RateIndex].Min = ConvertTo64Bit (Rate->Low, Rate->High); > + > + Rate = &DescribeRates->Rates[RateOffset++]; > + // Maximum clock rate. > + RateArray[RateIndex].Max = ConvertTo64Bit (Rate->Low, Rate->High); > + > + Rate = &DescribeRates->Rates[RateOffset++]; > + // Step. > + RateArray[RateIndex++].Step = ConvertTo64Bit (Rate->Low, Rate->High); > + } > + } > + } while (NUM_REMAIN_RATES (DescribeRates->NumRatesFlags) != 0); > + > + // Update RateArraySize with RequiredArraySize. > + *RateArraySize = RequiredArraySize; > + > + return EFI_SUCCESS; > +} > + > +/** Get clock rate. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + @param[in] ClockId Identifier for the clock device. > + > + @param[out] Rate Clock rate. > + > + @retval EFI_SUCCESS Clock rate is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +ClockRateGet ( > + IN SCMI_CLOCK_PROTOCOL *This, > + IN UINT32 ClockId, > + OUT UINT64 *Rate > + ) > +{ > + EFI_STATUS Status; > + > + UINT32 *MessageParams; > + CLOCK_RATE_DWORD *ClockRate; > + SCMI_COMMAND Cmd; > + > + UINT32 PayloadLength; > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Fill arguments for clock protocol command. > + *MessageParams = ClockId; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK; > + Cmd.MessageId = SCMI_MESSAGE_ID_CLOCK_RATE_GET; > + > + PayloadLength = sizeof (ClockId); > + > + // Execute and wait for response on a SCMI channel. > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&ClockRate > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *Rate = ((UINT64)ClockRate->High << 32) | ClockRate->Low; Should this not use the helper function? I could fix that up before committing, but would like confirmation on that. > + > + return EFI_SUCCESS; > +} > + > +/** Set clock rate. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + @param[in] ClockId Identifier for the clock device. > + @param[in] Rate Clock rate. > + > + @retval EFI_SUCCESS Clock rate set success. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +ClockRateSet ( > + IN SCMI_CLOCK_PROTOCOL *This, > + IN UINT32 ClockId, > + IN UINT64 Rate > + ) > +{ > + EFI_STATUS Status; > + CLOCK_RATE_SET_ATTRIBUTES *ClockRateSetAttributes; > + SCMI_COMMAND Cmd; > + UINT32 PayloadLength; > + > + Status = ScmiCommandGetPayload ((UINT32**)&ClockRateSetAttributes); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Fill arguments for clock protocol command. > + ClockRateSetAttributes->ClockId = ClockId; > + ClockRateSetAttributes->Flags = CLOCK_SET_DEFAULT_FLAGS; > + ClockRateSetAttributes->Rate.Low = (UINT32)Rate; > + ClockRateSetAttributes->Rate.High = (UINT32)(Rate >> 32); > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_CLOCK; > + Cmd.MessageId = SCMI_MESSAGE_ID_CLOCK_RATE_SET; > + > + PayloadLength = sizeof (CLOCK_RATE_SET_ATTRIBUTES); > + > + // Execute and wait for response on a SCMI channel. > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + NULL > + ); > + > + return Status; > +} > + > +// Instance of the SCMI clock management protocol. > +STATIC CONST SCMI_CLOCK_PROTOCOL ScmiClockProtocol = { > + ClockGetVersion, > + ClockGetTotalClocks, > + ClockGetClockAttributes, > + ClockDescribeRates, > + ClockRateGet, > + ClockRateSet > + }; > + > +/** Initialize clock management protocol and install protocol on a given handle. > + > + @param[in] Handle Handle to install clock management protocol. > + > + @retval EFI_SUCCESS Clock protocol interface installed successfully. > +**/ > +EFI_STATUS > +ScmiClockProtocolInit ( > + IN EFI_HANDLE* Handle > + ) > +{ > + return gBS->InstallMultipleProtocolInterfaces ( > + Handle, > + &gArmScmiClockProtocolGuid, > + &ScmiClockProtocol, > + NULL > + ); > +} > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c > new file mode 100644 > index 0000000000000000000000000000000000000000..2920c6f6f33c5bb8ac00c903a0b199ba5f06f4de > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c > @@ -0,0 +1,138 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "ArmScmiBaseProtocolPrivate.h" > +#include "ArmScmiClockProtocolPrivate.h" > +#include "ArmScmiPerformanceProtocolPrivate.h" > +#include "ScmiDxe.h" > +#include "ScmiPrivate.h" > + > +STATIC CONST SCMI_PROTOCOL_INIT_TABLE ProtocolInitFxns[MAX_PROTOCOLS] = { > + { ScmiBaseProtocolInit }, > + { NULL }, > + { NULL }, > + { ScmiPerformanceProtocolInit }, > + { ScmiClockProtocolInit }, > + { NULL } > +}; > + > +/** ARM SCMI driver entry point function. > + > + This function installs the SCMI Base protocol and a list of other > + protocols is queried using the Base protocol. If protocol is supported, > + driver will call each protocol init function to install the protocol on > + the ImageHandle. > + > + @param[in] ImageHandle Handle to this EFI Image which will be used to > + install Base, Clock and Performance protocols. > + @param[in] SystemTable A pointer to boot time system table. > + > + @retval EFI_SUCCESS Driver initalized successfully. > + @retval EFI_UNSUPPORTED If SCMI base protocol version is not supported. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +EFIAPI > +ArmScmiDxeEntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + SCMI_BASE_PROTOCOL *BaseProtocol; > + UINT32 Version; > + UINT32 Index; > + UINT32 NumProtocols; > + UINT32 ProtocolNo; > + UINT8 SupportedList[MAX_PROTOCOLS]; > + UINT32 SupportedListSize = sizeof (SupportedList); > + > + ProtocolNo = SCMI_PROTOCOL_ID_BASE & PROTOCOL_ID_MASK; > + > + // Every SCMI implementation must implement the base protocol. > + Status = ProtocolInitFxns[ProtocolNo].Init (&ImageHandle); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + Status = gBS->LocateProtocol ( > + &gArmScmiBaseProtocolGuid, > + NULL, > + (VOID**)&BaseProtocol > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + // Get SCMI Base protocol version. > + Status = BaseProtocol->GetVersion (BaseProtocol, &Version); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + if (Version != BASE_PROTOCOL_VERSION) { > + ASSERT (FALSE); > + return EFI_UNSUPPORTED; > + } > + > + // Apart from Base protocol, SCMI may implement various other protocols, > + // query total protocols implemented by the SCP firmware. > + NumProtocols = 0; > + Status = BaseProtocol->GetTotalProtocols (BaseProtocol, &NumProtocols); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + ASSERT (NumProtocols != 0); > + > + // Get the list of protocols supported by SCP firmware on the platform. > + Status = BaseProtocol->DiscoverListProtocols ( > + BaseProtocol, > + &SupportedListSize, > + SupportedList > + ); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + > + // Install supported protocol on ImageHandle. > + for (Index = 0; Index < NumProtocols; Index++) { > + ProtocolNo = SupportedList[Index] & PROTOCOL_ID_MASK; > + if (ProtocolInitFxns[ProtocolNo].Init != NULL) { > + Status = ProtocolInitFxns[ProtocolNo].Init (&ImageHandle); > + if (EFI_ERROR (Status)) { > + ASSERT (FALSE); > + return Status; > + } > + } > + } > + > + return EFI_SUCCESS; > +} > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h b/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h > new file mode 100644 > index 0000000000000000000000000000000000000000..29cdde173659c701116b021a3c437a92b473e4e5 > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h > @@ -0,0 +1,41 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > +#ifndef SCMI_DXE_H_ > +#define SCMI_DXE_H_ > + > +#define MAX_PROTOCOLS 6 > +#define PROTOCOL_ID_MASK 0xF > +#define MAX_VENDOR_LEN SCMI_MAX_STR_LEN > + > +/** Pointer to protocol initialization function. > + > + @param[in] Handle A pointer to the EFI_HANDLE on which the protocol > + interface is to be installed. > + > + @retval EFI_SUCCESS Protocol interface installed successfully. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_PROTOCOL_INIT_FXN)( > + IN EFI_HANDLE *Handle > + ); > + > +typedef struct { > + SCMI_PROTOCOL_INIT_FXN Init; > +} SCMI_PROTOCOL_INIT_TABLE; > + > +#endif /* SCMI_DXE_H_ */ > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c > new file mode 100644 > index 0000000000000000000000000000000000000000..ac32442ad838040721fd62faa806e82184f2b288 > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c > @@ -0,0 +1,457 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#include > +#include > +#include > + > +#include "ArmScmiPerformanceProtocolPrivate.h" > +#include "ScmiPrivate.h" > + > +/** Return version of the performance management protocol supported by SCP. > + firmware. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI performance management > + protocol. > + > + @retval EFI_SUCCESS The version is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +PerformanceGetVersion ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + OUT UINT32 *Version > + ) > +{ > + return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_PERFORMANCE, Version); > +} > + > +/** Return protocol attributes of the performance management protocol. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + > + @param[out] Attributes Protocol attributes. > + > + @retval EFI_SUCCESS Protocol attributes are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +PerformanceGetAttributes ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES *Attributes > + ) > +{ > + EFI_STATUS Status; > + UINT32* ReturnValues; > + > + Status = ScmiGetProtocolAttributes ( > + SCMI_PROTOCOL_ID_PERFORMANCE, > + &ReturnValues > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + memcpy ( Urgh, missed this one on previous passes. Surely this should be CopyMem? > + Attributes, > + ReturnValues, > + sizeof (SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES) > + ); > + > + return EFI_SUCCESS; > +} > + > +/** Return performance domain attributes. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + > + @param[out] Attributes Performance domain attributes. > + > + @retval EFI_SUCCESS Domain attributes are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +PerformanceDomainAttributes ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES *DomainAttributes > + ) > +{ > + EFI_STATUS Status; > + UINT32 *MessageParams; > + UINT32 *ReturnValues; > + UINT32 PayloadLength; > + SCMI_COMMAND Cmd; > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams = DomainId; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_DOMAIN_ATTRIBUTES; > + > + PayloadLength = sizeof (DomainId); > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + &ReturnValues > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + memcpy ( CopyMem? > + DomainAttributes, > + ReturnValues, > + sizeof (SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES) > + ); > + > + return EFI_SUCCESS; > +} > + > +/** Return list of performance domain levels of a given domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + > + @param[out] NumLevels Total number of levels a domain can support. > + > + @param[in,out] LevelArraySize Size of the performance level array. > + > + @param[out] LevelArray Array of the performance levels. > + > + @retval EFI_SUCCESS Domain levels are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result. > + It has been updated to the size needed. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +STATIC > +EFI_STATUS > +PerformanceDescribeLevels ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + OUT UINT32 *NumLevels, > + IN OUT UINT32 *LevelArraySize, > + OUT SCMI_PERFORMANCE_LEVEL *LevelArray > + ) > +{ > + EFI_STATUS Status; > + UINT32 PayloadLength; > + SCMI_COMMAND Cmd; > + UINT32* MessageParams; > + UINT32 LevelIndex; > + UINT32 RequiredSize; > + UINT32 LevelNo; > + UINT32 ReturnNumLevels; > + UINT32 ReturnRemainNumLevels; > + > + PERF_DESCRIBE_LEVELS *Levels; > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + LevelIndex = 0; > + RequiredSize = 0; > + > + *MessageParams++ = DomainId; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS; > + > + do { > + > + *MessageParams = LevelIndex; > + > + // Note, PayloadLength is an IN/OUT parameter. > + PayloadLength = sizeof (DomainId) + sizeof (LevelIndex); > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&Levels > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ReturnNumLevels = NUM_PERF_LEVELS (Levels->NumLevels); > + ReturnRemainNumLevels = NUM_REMAIN_PERF_LEVELS (Levels->NumLevels); > + > + if (RequiredSize == 0) { > + *NumLevels = ReturnNumLevels + ReturnRemainNumLevels; > + > + RequiredSize = (*NumLevels) * sizeof (SCMI_PERFORMANCE_LEVEL); > + if (RequiredSize > (*LevelArraySize)) { > + // Update LevelArraySize with required size. > + *LevelArraySize = RequiredSize; > + return EFI_BUFFER_TOO_SMALL; > + } > + } > + > + for (LevelNo = 0; LevelNo < ReturnNumLevels; LevelNo++) { > + memcpy ( CopyMem? / Leif > + &LevelArray[LevelIndex++], > + &Levels->PerfLevel[LevelNo], > + sizeof (SCMI_PERFORMANCE_LEVEL) > + ); > + } > + > + } while (ReturnRemainNumLevels != 0); > + > + *LevelArraySize = RequiredSize; > + > + return EFI_SUCCESS; > +} > + > +/** Set performance limits of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + @param[in] Limit Performance limit to set. > + > + @retval EFI_SUCCESS Performance limits set successfully. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +PerformanceLimitsSet ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + IN SCMI_PERFORMANCE_LIMITS *Limits > + ) > +{ > + EFI_STATUS Status; > + UINT32 PayloadLength; > + SCMI_COMMAND Cmd; > + UINT32 *MessageParams; > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams++ = DomainId; > + *MessageParams++ = Limits->RangeMax; > + *MessageParams = Limits->RangeMin; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET; > + > + PayloadLength = sizeof (DomainId) + sizeof (SCMI_PERFORMANCE_LIMITS); > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + NULL > + ); > + > + return Status; > +} > + > +/** Get performance limits of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + > + @param[out] Limit Performance Limits of the domain. > + > + @retval EFI_SUCCESS Performance limits are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +PerformanceLimitsGet ( > + SCMI_PERFORMANCE_PROTOCOL *This, > + UINT32 DomainId, > + SCMI_PERFORMANCE_LIMITS *Limits > + ) > +{ > + EFI_STATUS Status; > + UINT32 PayloadLength; > + SCMI_COMMAND Cmd; > + UINT32 *MessageParams; > + > + SCMI_PERFORMANCE_LIMITS *ReturnValues; > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams = DomainId; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET; > + > + PayloadLength = sizeof (DomainId); > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + (UINT32**)&ReturnValues > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Limits->RangeMax = ReturnValues->RangeMax; > + Limits->RangeMin = ReturnValues->RangeMin; > + > + return EFI_SUCCESS; > +} > + > +/** Set performance level of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + @param[in] Level Performance level of the domain. > + > + @retval EFI_SUCCESS Performance level set successfully. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +PerformanceLevelSet ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + IN UINT32 Level > + ) > +{ > + EFI_STATUS Status; > + UINT32 PayloadLength; > + SCMI_COMMAND Cmd; > + UINT32 *MessageParams; > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams++ = DomainId; > + *MessageParams = Level; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET; > + > + PayloadLength = sizeof (DomainId) + sizeof (Level); > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + NULL > + ); > + > + return Status; > +} > + > +/** Get performance level of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + > + @param[out] Level Performance level of the domain. > + > + @retval EFI_SUCCESS Performance level got successfully. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +PerformanceLevelGet ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + OUT UINT32 *Level > + ) > +{ > + EFI_STATUS Status; > + UINT32 PayloadLength; > + SCMI_COMMAND Cmd; > + UINT32 *ReturnValues; > + UINT32 *MessageParams; > + > + Status = ScmiCommandGetPayload (&MessageParams); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *MessageParams = DomainId; > + > + Cmd.ProtocolId = SCMI_PROTOCOL_ID_PERFORMANCE; > + Cmd.MessageId = SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET; > + > + PayloadLength = sizeof (DomainId); > + > + Status = ScmiCommandExecute ( > + &Cmd, > + &PayloadLength, > + &ReturnValues > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *Level = *ReturnValues; > + > + return EFI_SUCCESS; > +} > + > +// Instance of the SCMI performance management protocol. > +STATIC CONST SCMI_PERFORMANCE_PROTOCOL PerformanceProtocol = { > + PerformanceGetVersion, > + PerformanceGetAttributes, > + PerformanceDomainAttributes, > + PerformanceDescribeLevels, > + PerformanceLimitsSet, > + PerformanceLimitsGet, > + PerformanceLevelSet, > + PerformanceLevelGet > +}; > + > +/** Initialize performance management protocol and install on a given Handle. > + > + @param[in] Handle Handle to install performance management > + protocol. > + > + @retval EFI_SUCCESS Performance protocol installed successfully. > +**/ > +EFI_STATUS > +ScmiPerformanceProtocolInit ( > + IN EFI_HANDLE* Handle > + ) > +{ > + return gBS->InstallMultipleProtocolInterfaces ( > + Handle, > + &gArmScmiPerformanceProtocolGuid, > + &PerformanceProtocol, > + NULL > + ); > +} > diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h b/ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h > new file mode 100644 > index 0000000000000000000000000000000000000000..df03655b8b021fe5fd63ceab0dd414906d2fb248 > --- /dev/null > +++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h > @@ -0,0 +1,174 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > +#ifndef SCMI_PRIVATE_H_ > +#define SCMI_PRIVATE_H_ > + > +// SCMI protocol IDs. > +typedef enum { > + SCMI_PROTOCOL_ID_BASE = 0x10, > + SCMI_PROTOCOL_ID_POWER_DOMAIN = 0x11, > + SCMI_PROTOCOL_ID_SYSTEM_POWER = 0x12, > + SCMI_PROTOCOL_ID_PERFORMANCE = 0x13, > + SCMI_PROTOCOL_ID_CLOCK = 0x14, > + SCMI_PROTOCOL_ID_SENSOR = 0x15 > +} SCMI_PROTOCOL_ID; > + > +// SCMI message types. > +typedef enum { > + SCMI_MESSAGE_TYPE_COMMAND = 0, > + SCMI_MESSAGE_TYPE_DELAYED_RESPONSE = 2, // Skipping 1 is deliberate. > + SCMI_MESSAGE_TYPE_NOTIFICATION = 3 > +} SCMI_MESSAGE_TYPE; > + > +// SCMI response error codes. > +typedef enum { > + SCMI_SUCCESS = 0, > + SCMI_NOT_SUPPORTED = -1, > + SCMI_INVALID_PARAMETERS = -2, > + SCMI_DENIED = -3, > + SCMI_NOT_FOUND = -4, > + SCMI_OUT_OF_RANGE = -5, > + SCMI_BUSY = -6, > + SCMI_COMMS_ERROR = -7, > + SCMI_GENERIC_ERROR = -8, > + SCMI_HARDWARE_ERROR = -9, > + SCMI_PROTOCOL_ERROR = -10 > +} SCMI_STATUS; > + > +// SCMI message IDs common to all protocols. > +typedef enum { > + SCMI_MESSAGE_ID_PROTOCOL_VERSION = 0x0, > + SCMI_MESSAGE_ID_PROTOCOL_ATTRIBUTES = 0x1, > + SCMI_MESSAGE_ID_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2 > +} SCMI_MESSAGE_ID; > + > +// Not defined in SCMI specification but will help to identify a message. > +typedef struct { > + SCMI_PROTOCOL_ID ProtocolId; > + UINT32 MessageId; > +} SCMI_COMMAND; > + > +#pragma pack(1) > + > +// Response to a SCMI command. > +typedef struct { > + INT32 Status; > + UINT32 ReturnValues[]; > +} SCMI_MESSAGE_RESPONSE; > + > +// Message header. MsgId[7:0], MsgType[9:8], ProtocolId[17:10] > +#define MESSAGE_TYPE_SHIFT 8 > +#define PROTOCOL_ID_SHIFT 10 > +#define SCMI_MESSAGE_HEADER(MsgId, MsgType, ProtocolId) ( \ > + MsgType << MESSAGE_TYPE_SHIFT | \ > + ProtocolId << PROTOCOL_ID_SHIFT | \ > + MsgId \ > + ) > +// SCMI message header. > +typedef struct { > + UINT32 MessageHeader; > +} SCMI_MESSAGE_HEADER; > + > +#pragma pack() > + > +/** Return a pointer to the message payload. > + > + @param[out] Payload Holds pointer to the message payload. > + > + @retval EFI_SUCCESS Payload holds a valid message payload pointer. > + @retval EFI_TIMEOUT Time out error if MTL channel is busy. > + @retval EFI_UNSUPPORTED If MTL channel is unsupported. > +**/ > +EFI_STATUS > +ScmiCommandGetPayload ( > + OUT UINT32** Payload > + ); > + > +/** Execute a SCMI command and receive a response. > + > + This function uses a MTL channel to transfer message to SCP > + and waits for a response. > + > + @param[in] Command Pointer to the SCMI command (Protocol ID > + and Message ID) > + > + @param[in,out] PayloadLength SCMI command message length. > + > + @param[out] OPTIONAL ReturnValues Pointer to SCMI response. > + > + @retval OUT EFI_SUCCESS Command sent and message received successfully. > + @retval OUT EFI_UNSUPPORTED Channel not supported. > + @retval OUT EFI_TIMEOUT Timeout on the channel. > + @retval OUT EFI_DEVICE_ERROR Channel not ready. > + @retval OUT EFI_DEVICE_ERROR Message Header corrupted. > + @retval OUT EFI_DEVICE_ERROR SCMI error. > +**/ > +EFI_STATUS > +ScmiCommandExecute ( > + IN SCMI_COMMAND *Command, > + IN OUT UINT32 *PayloadLength, > + OUT UINT32 **ReturnValues OPTIONAL > + ); > + > +/** Return protocol version from SCP for a given protocol ID. > + > + @param[in] Protocol ID Protocol ID. > + @param[out] Version Pointer to version of the protocol. > + > + @retval EFI_SUCCESS Version holds a valid version received > + from the SCP. > + @retval EFI_DEVICE_ERROR SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +ScmiGetProtocolVersion ( > + IN SCMI_PROTOCOL_ID ProtocolId, > + OUT UINT32 *Version > + ); > + > +/** Return protocol attributes from SCP for a given protocol ID. > + > + @param[in] Protocol ID Protocol ID. > + @param[out] ReturnValues Pointer to attributes of the protocol. > + > + @retval EFI_SUCCESS ReturnValues points to protocol attributes. > + @retval EFI_DEVICE_ERROR SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +ScmiGetProtocolAttributes ( > + IN SCMI_PROTOCOL_ID ProtocolId, > + OUT UINT32 **ReturnValues > + ); > + > +/** Return protocol message attributes from SCP for a given protocol ID. > + > + @param[in] Protocol ID Protocol ID. > + > + @param[out] Attributes Pointer to attributes of the protocol. > + > + @retval EFI_SUCCESS ReturnValues points to protocol message attributes. > + @retval EFI_DEVICE_ERROR SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +EFI_STATUS > +ScmiGetProtocolMessageAttributes ( > + IN SCMI_PROTOCOL_ID ProtocolId, > + OUT UINT32 **ReturnValues > + ); > + > +#endif /* SCMI_PRIVATE_H_ */ > diff --git a/ArmPkg/Include/Protocol/ArmScmi.h b/ArmPkg/Include/Protocol/ArmScmi.h > new file mode 100644 > index 0000000000000000000000000000000000000000..239abb97064578c949614f79a6a33fe1881c3c68 > --- /dev/null > +++ b/ArmPkg/Include/Protocol/ArmScmi.h > @@ -0,0 +1,27 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_H_ > +#define ARM_SCMI_H_ > + > +/* As per SCMI specification, maximum allowed ASCII string length > + for various return values/parameters of a SCMI message. > +*/ > +#define SCMI_MAX_STR_LEN 16 > + > +#endif /* ARM_SCMI_H_ */ > + > diff --git a/ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h b/ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h > new file mode 100644 > index 0000000000000000000000000000000000000000..ecc41f2181ecc9f835950ab46c7cfd2e476a7073 > --- /dev/null > +++ b/ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h > @@ -0,0 +1,174 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_BASE_PROTOCOL_H_ > +#define ARM_SCMI_BASE_PROTOCOL_H_ > + > +#include > + > +#define BASE_PROTOCOL_VERSION 0x10000 > + > +#define NUM_PROTOCOL_MASK 0xFFU > +#define NUM_AGENT_MASK 0xFFU > + > +#define NUM_AGENT_SHIFT 0x8 > + > +/** Returns total number of protocols that are > + implemented (excluding the Base protocol) > +*/ > +#define SCMI_TOTAL_PROTOCOLS(Attr) (Attr & NUM_PROTOCOL_MASK) > + > +// Returns total number of agents in the system. > +#define SCMI_TOTAL_AGENTS(Attr) ((Attr >> NUM_AGENT_SHIFT) & NUM_AGENT_MASK) > + > +#define ARM_SCMI_BASE_PROTOCOL_GUID { \ > + 0xd7e5abe9, 0x33ab, 0x418e, {0x9f, 0x91, 0x72, 0xda, 0xe2, 0xba, 0x8e, 0x2f} \ > + } > + > +extern EFI_GUID gArmScmiBaseProtocolGuid; > + > +typedef struct _SCMI_BASE_PROTOCOL SCMI_BASE_PROTOCOL; > + > +/** Return version of the Base protocol supported by SCP firmware. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI Base protocol. > + > + @retval EFI_SUCCESS The version of the protocol is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_BASE_GET_VERSION) ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT32 *Version > + ); > + > +/** Return total number of SCMI protocols supported by the SCP firmware. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] TotalProtocols Total number of SCMI protocols supported. > + > + @retval EFI_SUCCESS Total number of protocols supported are returned. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_BASE_GET_TOTAL_PROTOCOLS) ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT32 *TotalProtocols > + ); > + > +/** Return vendor name. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] VendorIdentifier Null terminated ASCII string of up to > + 16 bytes with a vendor name. > + > + @retval EFI_SUCCESS VendorIdentifier is returned. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_BASE_DISCOVER_VENDOR) ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] > + ); > + > +/** Return sub vendor name. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] VendorIdentifier Null terminated ASCII string of up to > + 16 bytes with a vendor name. > + > + @retval EFI_SUCCESS VendorIdentifier is returned. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_BASE_DISCOVER_SUB_VENDOR) ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN] > + ); > + > +/** Return implementation version. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] ImplementationVersion Vendor specific implementation version. > + > + @retval EFI_SUCCESS Implementation version is returned. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION) ( > + IN SCMI_BASE_PROTOCOL *This, > + OUT UINT32 *ImplementationVersion > + ); > + > +/** Return list of protocols. > + > + @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance. > + > + @param[out] ProtocolListSize Size of the ProtocolList. > + > + @param[out] ProtocolList Protocol list. > + > + @retval EFI_SUCCESS List of protocols is returned. > + @retval EFI_BUFFER_TOO_SMALL ProtocolListSize is too small for the result. > + It has been updated to the size needed. > + @retval EFI_DEVICE_ERROR SCP returns a SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_BASE_DISCOVER_LIST_PROTOCOLS) ( > + IN SCMI_BASE_PROTOCOL *This, > + IN OUT UINT32 *ProtocolListSize, > + OUT UINT8 *ProtocolList > + ); > + > +// Base protocol. > +typedef struct _SCMI_BASE_PROTOCOL { > + SCMI_BASE_GET_VERSION GetVersion; > + SCMI_BASE_GET_TOTAL_PROTOCOLS GetTotalProtocols; > + SCMI_BASE_DISCOVER_VENDOR DiscoverVendor; > + SCMI_BASE_DISCOVER_SUB_VENDOR DiscoverSubVendor; > + SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION DiscoverImplementationVersion; > + SCMI_BASE_DISCOVER_LIST_PROTOCOLS DiscoverListProtocols; > +} SCMI_BASE_PROTOCOL; > + > +// SCMI Message IDs for Base protocol. > +typedef enum { > + SCMI_MESSAGE_ID_BASE_DISCOVER_VENDOR = 0x3, > + SCMI_MESSAGE_ID_BASE_DISCOVER_SUB_VENDOR = 0x4, > + SCMI_MESSAGE_ID_BASE_DISCOVER_IMPLEMENTATION_VERSION = 0x5, > + SCMI_MESSAGE_ID_BASE_DISCOVER_LIST_PROTOCOLS = 0x6 > +} SCMI_MESSAGE_ID_BASE; > + > +#endif /* ARM_SCMI_BASE_PROTOCOL_H_ */ > + > diff --git a/ArmPkg/Include/Protocol/ArmScmiClockProtocol.h b/ArmPkg/Include/Protocol/ArmScmiClockProtocol.h > new file mode 100644 > index 0000000000000000000000000000000000000000..3db26cb0641c7377c022a8e00be9a51ee5dc7361 > --- /dev/null > +++ b/ArmPkg/Include/Protocol/ArmScmiClockProtocol.h > @@ -0,0 +1,218 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_CLOCK_PROTOCOL_H_ > +#define ARM_SCMI_CLOCK_PROTOCOL_H_ > + > +#include > + > +#define ARM_SCMI_CLOCK_PROTOCOL_GUID { \ > + 0x91ce67a8, 0xe0aa, 0x4012, {0xb9, 0x9f, 0xb6, 0xfc, 0xf3, 0x4, 0x8e, 0xaa} \ > + } > + > +extern EFI_GUID gArmScmiClockProtocolGuid; > + > +// Message Type for clock management protocol. > +typedef enum { > + SCMI_MESSAGE_ID_CLOCK_ATTRIBUTES = 0x3, > + SCMI_MESSAGE_ID_CLOCK_DESCRIBE_RATES = 0x4, > + SCMI_MESSAGE_ID_CLOCK_RATE_SET = 0x5, > + SCMI_MESSAGE_ID_CLOCK_RATE_GET = 0x6, > + SCMI_MESSAGE_ID_CLOCK_CONFIG_SET = 0x7 > +} SCMI_MESSAGE_ID_CLOCK; > + > +typedef enum { > + SCMI_CLOCK_RATE_FORMAT_DISCRETE, // Non-linear range. > + SCMI_CLOCK_RATE_FORMAT_LINEAR // Linear range. > +} SCMI_CLOCK_RATE_FORMAT; > + > +// Clock management protocol version. > +#define SCMI_CLOCK_PROTOCOL_VERSION 0x10000 > + > +#define SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_MASK 0xFFU > +#define SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_SHIFT 16 > +#define SCMI_CLOCK_PROTOCOL_NUM_CLOCKS_MASK 0xFFFFU > + > +/** Total number of pending asynchronous clock rates changes > + supported by the SCP, Attr Bits[23:16] > +*/ > +#define SCMI_CLOCK_PROTOCOL_MAX_ASYNC_CLK_RATES(Attr) ( \ > + (Attr >> SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_SHIFT) && \ > + SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_MASK) > + > +// Total of clock devices supported by the SCP, Attr Bits[15:0] > +#define SCMI_CLOCK_PROTOCOL_TOTAL_CLKS(Attr) (Attr & SCMI_CLOCK_PROTOCOL_NUM_CLOCKS_MASK) > + > +#pragma pack(1) > + > +/* Depending on the format (linear/non-linear) supported by a clock device > + either Rate or Min/Max/Step triplet is valid. > +*/ > +typedef struct { > + union { > + UINT64 Min; > + UINT64 Rate; > + }; > + UINT64 Max; > + UINT64 Step; > +} SCMI_CLOCK_RATE; > + > +#pragma pack() > + > +typedef struct _SCMI_CLOCK_PROTOCOL SCMI_CLOCK_PROTOCOL; > + > +// Protocol Interface functions. > + > +/** Return version of the clock management protocol supported by SCP firmware. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI Clock management protocol. > + > + @retval EFI_SUCCESS The version is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_CLOCK_GET_VERSION) ( > + IN SCMI_CLOCK_PROTOCOL *This, > + OUT UINT32 *Version > + ); > + > +/** Return total number of clock devices supported by the clock management > + protocol. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + > + @param[out] TotalClocks Total number of clocks supported. > + > + @retval EFI_SUCCESS Total number of clocks supported is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_CLOCK_GET_TOTAL_CLOCKS) ( > + IN SCMI_CLOCK_PROTOCOL *This, > + OUT UINT32 *TotalClocks > + ); > + > +/** Return attributes of a clock device. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + @param[in] ClockId Identifier for the clock device. > + > + @param[out] Enabled If TRUE, the clock device is enabled. > + @param[out] ClockAsciiName A NULL terminated ASCII string with the clock > + name, of up to 16 bytes. > + > + @retval EFI_SUCCESS Clock device attributes are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_CLOCK_GET_CLOCK_ATTRIBUTES) ( > + IN SCMI_CLOCK_PROTOCOL *This, > + IN UINT32 ClockId, > + OUT BOOLEAN *Enabled, > + OUT CHAR8 *ClockAsciiName > + ); > + > +/** Return list of rates supported by a given clock device. > + > + @param[in] This A pointer to SCMI_CLOCK_PROTOCOL Instance. > + @param[in] ClockId Identifier for the clock device. > + > + @param[out] Format SCMI_CLOCK_RATE_FORMAT_DISCRETE: Clock device > + supports range of clock rates which are non-linear. > + > + SCMI_CLOCK_RATE_FORMAT_LINEAR: Clock device supports > + range of linear clock rates from Min to Max in steps. > + > + @param[out] TotalRates Total number of rates. > + > + @param[in,out] RateArraySize Size of the RateArray. > + > + @param[out] RateArray List of clock rates. > + > + @retval EFI_SUCCESS List of clock rates are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval EFI_BUFFER_TOO_SMALL RateArraySize is too small for the result. > + It has been updated to the size needed. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_CLOCK_DESCRIBE_RATES) ( > + IN SCMI_CLOCK_PROTOCOL *This, > + IN UINT32 ClockId, > + OUT SCMI_CLOCK_RATE_FORMAT *Format, > + OUT UINT32 *TotalRates, > + IN OUT UINT32 *RateArraySize, > + OUT SCMI_CLOCK_RATE *RateArray > + ); > + > +/** Get clock rate. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + @param[in] ClockId Identifier for the clock device. > + > + @param[out] Rate Clock rate. > + > + @retval EFI_SUCCESS Clock rate is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_CLOCK_RATE_GET) ( > + IN SCMI_CLOCK_PROTOCOL *This, > + IN UINT32 ClockId, > + OUT UINT64 *Rate > + ); > + > +/** Set clock rate. > + > + @param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance. > + @param[in] ClockId Identifier for the clock device. > + @param[in] Rate Clock rate. > + > + @retval EFI_SUCCESS Clock rate set success. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_CLOCK_RATE_SET) ( > + IN SCMI_CLOCK_PROTOCOL *This, > + IN UINT32 ClockId, > + IN UINT64 Rate > + ); > + > +typedef struct _SCMI_CLOCK_PROTOCOL { > + SCMI_CLOCK_GET_VERSION GetVersion; > + SCMI_CLOCK_GET_TOTAL_CLOCKS GetTotalClocks; > + SCMI_CLOCK_GET_CLOCK_ATTRIBUTES GetClockAttributes; > + SCMI_CLOCK_DESCRIBE_RATES DescribeRates; > + SCMI_CLOCK_RATE_GET RateGet; > + SCMI_CLOCK_RATE_SET RateSet; > +} SCMI_CLOCK_PROTOCOL; > + > +#endif /* ARM_SCMI_CLOCK_PROTOCOL_H_ */ > + > diff --git a/ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h b/ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h > new file mode 100644 > index 0000000000000000000000000000000000000000..1d1af6f8bee0c00bbe6b4774036c87c988a4f4af > --- /dev/null > +++ b/ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h > @@ -0,0 +1,265 @@ > +/** @file > + > + Copyright (c) 2017-2018, Arm Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > + System Control and Management Interface V1.0 > + http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/ > + DEN0056A_System_Control_and_Management_Interface.pdf > +**/ > + > +#ifndef ARM_SCMI_PERFORMANCE_PROTOCOL_H_ > +#define ARM_SCMI_PERFORMANCE_PROTOCOL_H_ > + > +#include > + > +#define PERFORMANCE_PROTOCOL_VERSION 0x10000 > + > +#define ARM_SCMI_PERFORMANCE_PROTOCOL_GUID { \ > + 0x9b8ba84, 0x3dd3, 0x49a6, {0xa0, 0x5a, 0x31, 0x34, 0xa5, 0xf0, 0x7b, 0xad} \ > + } > + > +extern EFI_GUID gArmScmiPerformanceProtocolGuid; > + > +typedef struct _SCMI_PERFORMANCE_PROTOCOL SCMI_PERFORMANCE_PROTOCOL; > + > +#pragma pack(1) > + > +#define POWER_IN_MW_SHIFT 16 > +#define POWER_IN_MW_MASK 0x1 > +#define NUM_PERF_DOMAINS_MASK 0xFFFF > + > +// Total number of performance domains, Attr Bits [15:0] > +#define SCMI_PERF_TOTAL_DOMAINS(Attr) (Attr & NUM_PERF_DOMAINS_MASK) > + > +// A flag to express power values in mW or platform specific way, Attr Bit [16] > +#define SCMI_PERF_POWER_IN_MW(Attr) ((Attr >> POWER_IN_MW_SHIFT) & \ > + POWER_IN_MW_MASK) > + > +// Performance protocol attributes return values. > +typedef struct { > + UINT32 Attributes; > + UINT64 StatisticsAddress; > + UINT32 StatisticsLen; > +} SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES; > + > +#define SCMI_PERF_SUPPORT_LVL_CHANGE_NOTIFY(Attr) ((Attr >> 28) & 0x1) > +#define SCMI_PERF_SUPPORT_LIM_CHANGE_NOTIFY(Attr) ((Attr >> 29) & 0x1) > +#define SCMI_PERF_SUPPORT_SET_LVL(Attr) ((Attr >> 30) & 0x1) > +#define SCMI_PERF_SUPPORT_SET_LIM(Attr) ((Attr >> 31) & 0x1) > +#define SCMI_PERF_RATE_LIMIT(RateLimit) (RateLimit & 0xFFF) > + > +// Performance protocol domain attributes. > +typedef struct { > + UINT32 Attributes; > + UINT32 RateLimit; > + UINT32 SustainedFreq; > + UINT32 SustainedPerfLevel; > + UINT8 Name[SCMI_MAX_STR_LEN]; > +} SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES; > + > +// Worst case latency in microseconds, Bits[15:0] > +#define PERF_LATENCY_MASK 0xFFFF > +#define SCMI_PERFORMANCE_PROTOCOL_LATENCY(Latency) (Latency & PERF_LATENCY_MASK) > + > +// Performance protocol performance level. > +typedef struct { > + UINT32 Level; > + UINT32 PowerCost; > + UINT32 Latency; > +} SCMI_PERFORMANCE_LEVEL; > + > +// Performance protocol performance limit. > +typedef struct { > + UINT32 RangeMax; > + UINT32 RangeMin; > +} SCMI_PERFORMANCE_LIMITS; > + > +#pragma pack() > + > +/** Return version of the performance management protocol supported by SCP. > + firmware. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + > + @param[out] Version Version of the supported SCMI performance management > + protocol. > + > + @retval EFI_SUCCESS The version is returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_PERFORMANCE_GET_VERSION) ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + OUT UINT32 *Version > + ); > + > +/** Return protocol attributes of the performance management protocol. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + > + @param[out] Attributes Protocol attributes. > + > + @retval EFI_SUCCESS Protocol attributes are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_PERFORMANCE_GET_ATTRIBUTES) ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES *Attributes > + > + ); > + > +/** Return performance domain attributes. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + > + @param[out] Attributes Performance domain attributes. > + > + @retval EFI_SUCCESS Domain attributes are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_PERFORMANCE_GET_DOMAIN_ATTRIBUTES) ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES *DomainAttributes > + ); > + > +/** Return list of performance domain levels of a given domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + > + @param[out] NumLevels Total number of levels a domain can support. > + > + @param[in,out] LevelArraySize Size of the performance level array. > + > + @param[out] LevelArray Array of the performance levels. > + > + @retval EFI_SUCCESS Domain levels are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result. > + It has been updated to the size needed. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_PERFORMANCE_DESCRIBE_LEVELS) ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + OUT UINT32 *NumLevels, > + IN OUT UINT32 *LevelArraySize, > + OUT SCMI_PERFORMANCE_LEVEL *LevelArray > + ); > + > +/** Set performance limits of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + @param[in] Limit Performance limit to set. > + > + @retval EFI_SUCCESS Performance limits set successfully. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_PERFORMANCE_LIMITS_SET) ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + IN SCMI_PERFORMANCE_LIMITS *Limits > + ); > + > +/** Get performance limits of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + > + @param[out] Limit Performance Limits of the domain. > + > + @retval EFI_SUCCESS Performance limits are returned. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_PERFORMANCE_LIMITS_GET) ( > + SCMI_PERFORMANCE_PROTOCOL *This, > + UINT32 DomainId, > + SCMI_PERFORMANCE_LIMITS *Limits > + ); > + > +/** Set performance level of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + @param[in] Level Performance level of the domain. > + > + @retval EFI_SUCCESS Performance level set successfully. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_PERFORMANCE_LEVEL_SET) ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + IN UINT32 Level > + ); > + > +/** Get performance level of a domain. > + > + @param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance. > + @param[in] DomainId Identifier for the performance domain. > + > + @param[out] Level Performance level of the domain. > + > + @retval EFI_SUCCESS Performance level got successfully. > + @retval EFI_DEVICE_ERROR SCP returns an SCMI error. > + @retval !(EFI_SUCCESS) Other errors. > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *SCMI_PERFORMANCE_LEVEL_GET) ( > + IN SCMI_PERFORMANCE_PROTOCOL *This, > + IN UINT32 DomainId, > + OUT UINT32 *Level > + ); > + > +typedef struct _SCMI_PERFORMANCE_PROTOCOL { > + SCMI_PERFORMANCE_GET_VERSION GetVersion; > + SCMI_PERFORMANCE_GET_ATTRIBUTES GetProtocolAttributes; > + SCMI_PERFORMANCE_GET_DOMAIN_ATTRIBUTES GetDomainAttributes; > + SCMI_PERFORMANCE_DESCRIBE_LEVELS DescribeLevels; > + SCMI_PERFORMANCE_LIMITS_SET LimitsSet; > + SCMI_PERFORMANCE_LIMITS_GET LimitsGet; > + SCMI_PERFORMANCE_LEVEL_SET LevelSet; > + SCMI_PERFORMANCE_LEVEL_GET LevelGet; > +} SCMI_PERFORMANCE_PROTOCOL; > + > +typedef enum { > + SCMI_MESSAGE_ID_PERFORMANCE_DOMAIN_ATTRIBUTES = 0x3, > + SCMI_MESSAGE_ID_PERFORMANCE_DESCRIBE_LEVELS = 0x4, > + SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_SET = 0x5, > + SCMI_MESSAGE_ID_PERFORMANCE_LIMITS_GET = 0x6, > + SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_SET = 0x7, > + SCMI_MESSAGE_ID_PERFORMANCE_LEVEL_GET = 0x8, > +} SCMI_MESSAGE_ID_PERFORMANCE; > + > +#endif /* ARM_SCMI_PERFORMANCE_PROTOCOL_H_ */ > + > -- > 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' > >