From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2a00:1450:4864:20::341; helo=mail-wm1-x341.google.com; envelope-from=leif.lindholm@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-wm1-x341.google.com (mail-wm1-x341.google.com [IPv6:2a00:1450:4864:20::341]) (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 82D552119C8AB for ; Fri, 14 Dec 2018 10:12:40 -0800 (PST) Received: by mail-wm1-x341.google.com with SMTP id y1so6518240wmi.3 for ; Fri, 14 Dec 2018 10:12:40 -0800 (PST) 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=7Doaf3Q2zHwvuN4nVbFfoV4trOvZ5QvUOiBaGsr4558=; b=co4T0wBBlxgEW5nOdiGR9C/KdcE5F/b/8q8M6YtbljlgiKBAKw51LMA3MCwqytuXyZ /LBxsn/3Gh2rxx9q5C5kBsS2HFYfJWNvny/MuK1MYZi0jP/gr6SOeLUH57xt692t8jjd XwtGCxqCb3zmSlUQDGPa2wJpKotm+tzKZmcUU= 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=7Doaf3Q2zHwvuN4nVbFfoV4trOvZ5QvUOiBaGsr4558=; b=uDcNC6u26thdUxEn8cuWjdz18sUddNxXC1rItmLuYwKCbZcdwUDkJKaMuxxCo+Uxgh lqMo9uH3o4GUz5I1HlDYZW78Qhxs3vBs8xXg4fUjJ3D2ONOJS9nVJyOuiT5Wp9NDfmBS rhM0IVwE7EmtXBqjdRHUSQYK2KobLuVqEAB/9+nG3YLS4PW5i9sv7tnZs3oCAIaoDU0k Ahi6JITwjWwpbHsdxjlPLuy+8yk9IfrqGM3kUW2jc66c2XrUoY4Y1tEd63W4E/SiG2Y+ cyi4VwxhDkuYEQ401rQqEcB0yJVqtqyfwIkM8ppMytsAYmzUpRNND+5lwyTr1PbJ23Tr BNMQ== X-Gm-Message-State: AA+aEWbEOfOuJy+kPCtvXlycXq2GIUoXHfYEbeMpFK4q49WcDKSCqQIy +hdv3b01nP4rF7Jnu2/R/v9xhg== X-Google-Smtp-Source: AFSGD/XOYvEvI3NBkxwsVPWfbRIbH92RG407CuiGhFc0vJ7YtpSANzryyV8muHGtyHDecS5P987cjg== X-Received: by 2002:a1c:2902:: with SMTP id p2mr4078855wmp.19.1544811158296; Fri, 14 Dec 2018 10:12:38 -0800 (PST) Received: from bivouac.eciton.net (bivouac.eciton.net. [2a00:1098:0:86:1000:23:0:2]) by smtp.gmail.com with ESMTPSA id o64sm4336588wmo.47.2018.12.14.10.12.36 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 14 Dec 2018 10:12:36 -0800 (PST) Date: Fri, 14 Dec 2018 18:12:35 +0000 From: Leif Lindholm To: Chris Co Cc: "edk2-devel@lists.01.org" , Ard Biesheuvel , Michael D Kinney Message-ID: <20181214181235.p4knundhknrrpnvn@bivouac.eciton.net> References: <20180921082542.35768-1-christopher.co@microsoft.com> <20180921082542.35768-19-christopher.co@microsoft.com> MIME-Version: 1.0 In-Reply-To: <20180921082542.35768-19-christopher.co@microsoft.com> User-Agent: NeoMutt/20170113 (1.7.2) Subject: Re: [PATCH edk2-platforms 18/27] Silicon/NXP: Add i.MX6 Clock Library X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Dec 2018 18:12:41 -0000 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Sep 21, 2018 at 08:26:11AM +0000, Chris Co wrote: > This adds support for managing clocks on NXP i.MX6 SoC. It will > manipulate the Clock Gating registers (CCGR). > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Christopher Co > Cc: Ard Biesheuvel > Cc: Leif Lindholm > Cc: Michael D Kinney > --- > Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c | 1876 ++++++++++++++++++++ > Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf | 46 + > Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h | 221 +++ > 3 files changed, 2143 insertions(+) > > diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c > new file mode 100644 > index 000000000000..07958b1e392d > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr.c > @@ -0,0 +1,1876 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. 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. > +* > +**/ > + > +#include > + > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include "iMX6ClkPwr_private.h" > + > +static IMX_CLOCK_TREE_CACHE mImxpClockPwrCache; // Cached clock value STATIC > + > +STATIC CONST IMX_CCGR_INDEX ImxpCcgrIndexMap[] = { Add m-prefix. > + {0, 0}, // MX6_AIPS_TZ1_CLK_ENABLE > + {0, 1}, // MX6_AIPS_TZ2_CLK_ENABLE > + {0, 2}, // MX6_APBHDMA_HCLK_ENABLE > + {0, 3}, // MX6_ASRC_CLK_ENABLE > + {0, 4}, // MX6_CAAM_SECURE_MEM_CLK_ENABLE > + {0, 5}, // MX6_CAAM_WRAPPER_ACLK_ENABLE > + {0, 6}, // MX6_CAAM_WRAPPER_IPG_ENABLE > + {0, 7}, // MX6_CAN1_CLK_ENABLE > + {0, 8}, // MX6_CAN1_SERIAL_CLK_ENABLE > + {0, 9}, // MX6_CAN2_CLK_ENABLE > + {0, 10}, // MX6_CAN2_SERIAL_CLK_ENABLE > + {0, 11}, // MX6_ARM_DBG_CLK_ENABLE > + {0, 12}, // MX6_DCIC1_CLK_ENABLE > + {0, 13}, // MX6_DCIC2_CLK_ENABLE > + {0, 14}, // MX6_DTCP_CLK_ENABLE > + {1, 0}, // MX6_ECSPI1_CLK_ENABLE > + {1, 1}, // MX6_ECSPI2_CLK_ENABLE > + {1, 2}, // MX6_ECSPI3_CLK_ENABLE > + {1, 3}, // MX6_ECSPI4_CLK_ENABLE > + {1, 4}, // MX6_ECSPI5_CLK_ENABLE > + {1, 5}, // MX6_ENET_CLK_ENABLE > + {1, 6}, // MX6_EPIT1_CLK_ENABLE > + {1, 7}, // MX6_EPIT2_CLK_ENABLE > + {1, 8}, // MX6_ESAI_CLK_ENABLE > + {1, 10}, // MX6_GPT_CLK_ENABLE > + {1, 11}, // MX6_GPT_SERIAL_CLK_ENABLE > + {1, 12}, // MX6_GPU2D_CLK_ENABLE > + {1, 13}, // MX6_GPU3D_CLK_ENABLE > + {2, 0}, // MX6_HDMI_TX_ENABLE > + {2, 2}, // MX6_HDMI_TX_ISFRCLK_ENABLE > + {2, 3}, // MX6_I2C1_SERIAL_CLK_ENABLE > + {2, 4}, // MX6_I2C2_SERIAL_CLK_ENABLE > + {2, 5}, // MX6_I2C3_SERIAL_CLK_ENABLE > + {2, 6}, // MX6_IIM_CLK_ENABLE > + {2, 7}, // MX6_IOMUX_IPT_CLK_IO_ENABLE > + {2, 8}, // MX6_IPMUX1_CLK_ENABLE > + {2, 9}, // MX6_IPMUX2_CLK_ENABLE > + {2, 10}, // MX6_IPMUX3_CLK_ENABLE > + {2, 11}, // MX6_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE > + {2, 12}, // MX6_IPSYNC_IP2APB_TZASC2_IPG_MASTER_CLK_ENABLE > + {2, 13}, // MX6_IPSYNC_VDOA_IPG_MASTER_CLK_ENABLE > + {3, 0}, // MX6_IPU1_IPU_CLK_ENABLE > + {3, 1}, // MX6_IPU1_IPU_DI0_CLK_ENABLE > + {3, 2}, // MX6_IPU1_IPU_DI1_CLK_ENABLE > + {3, 3}, // MX6_IPU2_IPU_CLK_ENABLE > + {3, 4}, // MX6_IPU2_IPU_DI0_CLK_ENABLE > + {3, 5}, // MX6_IPU2_IPU_DI1_CLK_ENABLE > + {3, 6}, // MX6_LDB_DI0_CLK_ENABLE > + {3, 7}, // MX6_LDB_DI1_CLK_ENABLE > + {3, 8}, // MX6_MIPI_CORE_CFG_CLK_ENABLE > + {3, 9}, // MX6_MLB_CLK_ENABLE > + {3, 10}, // MX6_MMDC_CORE_ACLK_FAST_CORE_P0_ENABLE > + {3, 12}, // MX6_MMDC_CORE_IPG_CLK_P0_ENABLE > + {3, 14}, // MX6_OCRAM_CLK_ENABLE > + {3, 15}, // MX6_OPENVGAXICLK_CLK_ROOT_ENABLE > + {4, 0}, // MX6_PCIE_ROOT_ENABLE > + {4, 4}, // MX6_PL301_MX6QFAST1_S133CLK_ENABLE > + {4, 6}, // MX6_PL301_MX6QPER1_BCHCLK_ENABLE > + {4, 7}, // MX6_PL301_MX6QPER2_MAINCLK_ENABLE > + {4, 8}, // MX6_PWM1_CLK_ENABLE > + {4, 9}, // MX6_PWM2_CLK_ENABLE > + {4, 10}, // MX6_PWM3_CLK_ENABLE > + {4, 11}, // MX6_PWM4_CLK_ENABLE > + {4, 12}, // MX6_RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE > + {4, 13}, // MX6_RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE > + {4, 14}, // MX6_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE > + {4, 15}, // MX6_RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE > + {5, 0}, // MX6_ROM_CLK_ENABLE > + {5, 2}, // MX6_SATA_CLK_ENABLE > + {5, 3}, // MX6_SDMA_CLK_ENABLE > + {5, 6}, // MX6_SPBA_CLK_ENABLE > + {5, 7}, // MX6_SPDIF_CLK_ENABLE > + {5, 9}, // MX6_SSI1_CLK_ENABLE > + {5, 10}, // MX6_SSI2_CLK_ENABLE > + {5, 11}, // MX6_SSI3_CLK_ENABLE > + {5, 12}, // MX6_UART_CLK_ENABLE > + {5, 13}, // MX6_UART_SERIAL_CLK_ENABLE > + {6, 0}, // MX6_USBOH3_CLK_ENABLE > + {6, 1}, // MX6_USDHC1_CLK_ENABLE > + {6, 2}, // MX6_USDHC2_CLK_ENABLE > + {6, 3}, // MX6_USDHC3_CLK_ENABLE > + {6, 4}, // MX6_USDHC4_CLK_ENABLE > + {6, 5}, // MX6_EIM_SLOW_CLK_ENABLE > + {6, 6}, // MX6_VDOAXICLK_CLK_ENABLE > + {6, 7}, // MX6_VPU_CLK_ENABLE > +}; > + > +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) > +STATIC IMX_CLOCK_CONTEXT ExpectedClocks[] = { Add m-prefix. > + {IMX_OSC_CLK, {24000000, IMX_CLK_NONE}}, > + {IMX_PLL1_MAIN_CLK, {792000000, IMX_OSC_CLK}}, > + {IMX_PLL2_MAIN_CLK, {528000000, IMX_OSC_CLK}}, > + {IMX_PLL2_PFD0, {352000000, IMX_PLL2_MAIN_CLK}}, > + {IMX_PLL2_PFD1, {594000000, IMX_PLL2_MAIN_CLK}}, > + {IMX_PLL2_PFD2, {396000000, IMX_PLL2_MAIN_CLK}}, > + {IMX_PLL3_MAIN_CLK, {480000000, IMX_OSC_CLK}}, > + {IMX_PLL3_PFD0, {720000000, IMX_PLL3_MAIN_CLK}}, > + {IMX_PLL3_PFD1, {540000000, IMX_PLL3_MAIN_CLK}}, > + {IMX_PLL3_PFD2, {508235294, IMX_PLL3_MAIN_CLK}}, > + {IMX_PLL3_PFD3, {454736842, IMX_PLL3_MAIN_CLK}}, > + {IMX_AXI_CLK_ROOT, {264000000, IMX_PERIPH_CLK}}, > + {IMX_MMDC_CH0_CLK_ROOT, {528000000, IMX_PERIPH_CLK}}, > +}; > +#elif defined(CPU_IMX6SDL) > +STATIC IMX_CLOCK_CONTEXT ExpectedClocks[] = { Add m-prefix. > + {IMX_OSC_CLK, {24000000, IMX_CLK_NONE}}, > + {IMX_PLL1_MAIN_CLK, {792000000, IMX_OSC_CLK}}, > + {IMX_PLL2_MAIN_CLK, {528000000, IMX_OSC_CLK}}, > + {IMX_PLL2_PFD0, {306580645, IMX_PLL2_MAIN_CLK}}, > + {IMX_PLL2_PFD1, {528000000, IMX_PLL2_MAIN_CLK}}, > + {IMX_PLL2_PFD2, {396000000, IMX_PLL2_MAIN_CLK}}, > + {IMX_PLL3_MAIN_CLK, {480000000, IMX_OSC_CLK}}, > + {IMX_PLL3_PFD0, {720000000, IMX_PLL3_MAIN_CLK}}, > + {IMX_PLL3_PFD1, {540000000, IMX_PLL3_MAIN_CLK}}, > + {IMX_PLL3_PFD2, {508235294, IMX_PLL3_MAIN_CLK}}, > + {IMX_PLL3_PFD3, {454736842, IMX_PLL3_MAIN_CLK}}, > + {IMX_AXI_CLK_ROOT, {198000000, IMX_PERIPH_CLK}}, > + {IMX_MMDC_CH0_CLK_ROOT, {396000000, IMX_PERIPH_CLK}}, > +}; > +#endif > + > +/** > + Get the CCGR register index and gate number for a clock gate. > + > + @param[in] ClockGate Specific clock gate to get CCGR index > +**/ > +IMX_CCGR_INDEX > +ImxpCcgrIndexFromClkGate ( > + IN IMX_CLK_GATE ClockGate > + ) > +{ > + return ImxpCcgrIndexMap[ClockGate]; > +} > + > +CONST CHAR16* > +StringFromImxClk ( > + IN IMX_CLK Value > + ) > +{ > + switch (Value) { > + case IMX_CLK_NONE: > + return L"(none)"; Is this swithch really worth it? Could this string be added to the structs above instead? > + case IMX_OSC_CLK: > + return L"OSC_CLK"; > + case IMX_PLL1_MAIN_CLK: > + return L"PLL1_MAIN_CLK"; > + case IMX_PLL2_MAIN_CLK: > + return L"PLL2_MAIN_CLK"; > + case IMX_PLL2_PFD0: > + return L"PLL2_PFD0"; > + case IMX_PLL2_PFD1: > + return L"PLL2_PFD1"; > + case IMX_PLL2_PFD2: > + return L"PLL2_PFD2"; > + case IMX_PLL3_MAIN_CLK: > + return L"PLL3_MAIN_CLK"; > + case IMX_PLL3_PFD0: > + return L"PLL3_PFD0"; > + case IMX_PLL3_PFD1: > + return L"PLL3_PFD1"; > + case IMX_PLL3_PFD2: > + return L"PLL3_PFD2"; > + case IMX_PLL3_PFD3: > + return L"PLL3_PFD3"; > + case IMX_PLL4_MAIN_CLK: > + return L"PLL4_MAIN_CLK"; > + case IMX_PLL5_MAIN_CLK: > + return L"PLL5_MAIN_CLK"; > + case IMX_CLK1: > + return L"CLK1"; > + case IMX_CLK2: > + return L"CLK2"; > + case IMX_PLL1_SW_CLK: > + return L"PLL1_SW_CLK"; > + case IMX_STEP_CLK: > + return L"STEP_CLK"; > + case IMX_PLL3_SW_CLK: > + return L"PLL3_SW_CLK"; > + case IMX_AXI_ALT: > + return L"AXI_ALT"; > + case IMX_AXI_CLK_ROOT: > + return L"AXI_CLK_ROOT"; > + case IMX_PERIPH_CLK2: > + return L"PERIPH_CLK2"; > + case IMX_PERIPH_CLK: > + return L"PERIPH_CLK"; > + case IMX_PRE_PERIPH_CLK: > + return L"PRE_PERIPH_CLK"; > + case IMX_PRE_PERIPH2_CLK: > + return L"PRE_PERIPH2_CLK"; > + case IMX_PERIPH2_CLK: > + return L"PERIPH2_CLK"; > + case IMX_ARM_CLK_ROOT: > + return L"ARM_CLK_ROOT"; > + case IMX_MMDC_CH0_CLK_ROOT: > + return L"MMDC_CH0_CLK_ROOT"; > + case IMX_MMDC_CH1_CLK_ROOT: > + return L"MMDC_CH1_CLK_ROOT"; > + case IMX_AHB_CLK_ROOT: > + return L"AHB_CLK_ROOT"; > + case IMX_IPG_CLK_ROOT: > + return L"IPG_CLK_ROOT"; > + case IMX_PERCLK_CLK_ROOT: > + return L"PERCLK_CLK_ROOT"; > + case IMX_USDHC1_CLK_ROOT: > + return L"USDHC1_CLK_ROOT"; > + case IMX_USDHC2_CLK_ROOT: > + return L"USDHC2_CLK_ROOT"; > + case IMX_USDHC3_CLK_ROOT: > + return L"USDHC3_CLK_ROOT"; > + case IMX_USDHC4_CLK_ROOT: > + return L"USDHC4_CLK_ROOT"; > + case IMX_SSI1_CLK_ROOT: > + return L"SSI1_CLK_ROOT"; > + case IMX_SSI2_CLK_ROOT: > + return L"SSI2_CLK_ROOT"; > + case IMX_SSI3_CLK_ROOT: > + return L"SSI3_CLK_ROOT"; > + case IMX_GPU2D_AXI_CLK_ROOT: > + return L"GPU2D_AXI_CLK_ROOT"; > + case IMX_GPU3D_AXI_CLK_ROOT: > + return L"GPU3D_AXI_CLK_ROOT"; > + case IMX_PCIE_AXI_CLK_ROOT: > + return L"PCIE_AXI_CLK_ROOT"; > + case IMX_VDO_AXI_CLK_ROOT: > + return L"VDO_AXI_CLK_ROOT"; > + case IMX_IPU1_HSP_CLK_ROOT: > + return L"IPU1_HSP_CLK_ROOT"; > + case IMX_GPU2D_CORE_CLK_ROOT: > + return L"GPU2D_CORE_CLK_ROOT"; > + case IMX_ACLK_EIM_SLOW_CLK_ROOT: > + return L"ACLK_EIM_SLOW_CLK_ROOT"; > + case IMX_ACLK_CLK_ROOT: > + return L"ACLK_CLK_ROOT"; > + case IMX_ENFC_CLK_ROOT: > + return L"ENFC_CLK_ROOT"; > + case IMX_GPU3D_CORE_CLK_ROOT: > + return L"GPU3D_CORE_CLK_ROOT"; > + case IMX_GPU3D_SHADER_CLK_ROOT: > + return L"GPU3D_SHADER_CLK_ROOT"; > + case IMX_VPU_AXI_CLK_ROOT: > + return L"VPU_AXI_CLK_ROOT"; > + case IMX_IPU1_DI0_CLK_ROOT: > + return L"IPU1_DI0_CLK_ROOT"; > + case IMX_IPU1_DI1_CLK_ROOT: > + return L"IPU1_DI1_CLK_ROOT"; > + case IMX_LDB_DI0_SERIAL_CLK_ROOT: > + return L"LDB_DI0_SERIAL_CLK_ROOT"; > + case IMX_LDB_DI0_IPU: > + return L"LDB_DI0_IPU"; > + case IMX_LDB_DI1_SERIAL_CLK_ROOT: > + return L"LDB_DI1_SERIAL_CLK_ROOT"; > + case IMX_LDB_DI1_IPU: > + return L"LDB_DI1_IPU"; > + case IMX_SPDIF0_CLK_ROOT: > + return L"SPDIF0_CLK_ROOT"; > + case IMX_SPDIF1_CLK_ROOT: > + return L"SPDIF1_CLK_ROOT"; > + case IMX_ESAI_CLK_ROOT: > + return L"ESAI_CLK_ROOT"; > + case IMX_HSI_TX_CLK_ROOT: > + return L"HSI_TX_CLK_ROOT"; > + case IMX_CAN_CLK_ROOT: > + return L"CAN_CLK_ROOT"; > + case IMX_ECSPI_CLK_ROOT: > + return L"ECSPI_CLK_ROOT"; > + case IMX_UART_CLK_ROOT: > + return L"UART_CLK_ROOT"; > + case IMX_VIDEO_27M_CLK_ROOT: > + return L"VIDEO_27M_CLK_ROOT"; > +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) > + case IMX_IPU2_HSP_CLK_ROOT: > + return L"IPU2_HSP_CLK_ROOT"; > + case IMX_IPU2_DI0_CLK_ROOT: > + return L"IPU2_DI0_CLK_ROOT"; > + case IMX_IPU2_DI1_CLK_ROOT: > + return L"IPU2_DI1_CLK_ROOT"; > +#endif > + default: > + ASSERT (FALSE); > + return L"[Invalid IMX_CLK value]"; > + } > +} > + > +IMX_CLK > +ImxpClkFromBypassClkSource ( This (and other) helper functions appear to only be called from this file. Could they be made STATIC and dropped from the iMX6ClkPwr_private.h, or are they expected to be used elsewhere in future? > + IN IMX_PLL_BYPASS_CLK_SRC BypassClockSource > + ) > +{ > + switch (BypassClockSource) { > + case IMX_PLL_BYPASS_CLK_SRC_REF_CLK_24M: > + return IMX_OSC_CLK; > + case IMX_PLL_BYPASS_CLK_SRC_CLK1: > + return IMX_CLK1; > + case IMX_PLL_BYPASS_CLK_SRC_CLK2: > + return IMX_CLK2; > + case IMX_PLL_BYPASS_CLK_SRC_XOR: > + default: > + ASSERT (FALSE); > + return IMX_CLK_NONE; > + } > +} > + > +/** > + Configure the GPU clock tree so that GPU2D and GPU3D are clocked from > + the AXI clock root and are within the allowed frequency range. > + > + The GPU must be powered down, and GPU clocks must be gated when this > + function is called. > +**/ > +VOID > +ImxCcmConfigureGpuClockTree ( > + VOID > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; No Hungarian notation please. Please search/replace '*p' with '*' throughout the set. (Yes, I have accidentally let some through in the past, we'll get around to cleaning those up in the future.) > + IMX_CCM_CBCMR_REG CbcmrReg; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR); > + > + CbcmrReg.gpu2d_axi_clk_sel = IMX_CCM_GPU2D_AXI_CLK_SEL_AXI; > + CbcmrReg.gpu3d_axi_clk_sel = IMX_CCM_GPU3D_AXI_CLK_SEL_AXI; > + CbcmrReg.gpu2d_core_clk_sel = IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD0; > + CbcmrReg.gpu3d_core_clk_sel = IMX_CCM_GPU3D_CORE_CLK_SEL_MMDC_CH0_AXI; > + CbcmrReg.gpu3d_shader_clk_sel = IMX_CCM_GPU3D_SHADER_CLK_SEL_MMDC_CH0_AXI; > + CbcmrReg.gpu2d_core_clk_podf = 0; > + CbcmrReg.gpu3d_core_podf = 0; > + CbcmrReg.gpu3d_shader_podf = 0; > + > + ImxpClkPwrCacheReset (); > + MmioWrite32 ((UINTN) &pCcmRegisters->CBCMR, CbcmrReg.AsUint32); > +} > + > +/** > + Configure all of DIx clock tree for both IPU1 and IPU2. For flexibility > + purpose use PLL5 (PLL Video) as main reference clock. PLL 5 has flexible > + divider making it easily configurable. Muxing and clock programming needs > + when to be updated when supporting multiple display. > +**/ > +VOID > +ImxCcmConfigureIPUDIxClockTree ( > + VOID > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CHSCCDR_REG ChscddrReg; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + ChscddrReg.AsUint32 = MmioRead32 ((UINTN)&pCcmRegisters->CHSCCDR); > + > + // Setup muxing to pre-mux > + if (FeaturePcdGet (PcdLvdsEnable)) { > + ChscddrReg.ipu1_di0_clk_sel = IMX_CHSCCDR_IPU1_DI0_CLK_SEL_LDB_DI0_CLK; > + ChscddrReg.ipu1_di1_clk_sel = IMX_CHSCCDR_IPU1_DI0_CLK_SEL_LDB_DI0_CLK; > + } else { > + ChscddrReg.ipu1_di0_clk_sel = IMX_CHSCCDR_IPU1_DI0_CLK_SEL_PREMUX; > + ChscddrReg.ipu1_di1_clk_sel = IMX_CHSCCDR_IPU1_DI1_CLK_SEL_PREMUX; > + } > + ChscddrReg.ipu1_di0_podf = IMX_CHSCCDR_IPU1_DI0_PODF_DIV_1; > + ChscddrReg.ipu1_di1_podf = IMX_CHSCCDR_IPU1_DI1_PODF_DIV_1; > + ChscddrReg.ipu1_di0_pre_clk_sel = IMX_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_PLL5; > + ChscddrReg.ipu1_di1_pre_clk_sel = IMX_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_PLL5; > + > + MmioWrite32 ((UINTN)&pCcmRegisters->CHSCCDR, ChscddrReg.AsUint32); > +} > + > +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) > +/** > + Configure both LDB0/1 to use PLL5 clock > +**/ > +VOID > +ImxCcmConfigureIPULDBxClockTree ( > + VOID > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CS2CDR_REG Cs2cdrReg; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + Cs2cdrReg.AsUint32 = MmioRead32 ((UINTN)&pCcmRegisters->CS2CDR); > + > + Cs2cdrReg.ldb_di0_clk_sel = 0x0; > + Cs2cdrReg.ldb_di1_clk_sel = 0x0; > + > + MmioWrite32 ((UINTN)&pCcmRegisters->CS2CDR, Cs2cdrReg.AsUint32); > +} > +#endif > + > +/** > + Configure PLL 5 clock rate to the desired clock rate > +**/ > +VOID > +ImxSetClockRatePLL5 ( > + IN UINT32 ClockRate, > + IN IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT PostDivSelect > + ) > +{ > + volatile IMX_CCM_ANALOG_REGISTERS *pCcmAnalogRegisters; > + UINT32 Counter; > + UINT32 Denom; > + UINT32 DivSelect; > + UINT32 Numerator; > + IMX_CCM_PLL_VIDEO_CTRL_REG PllVideoCtrlClearReg; > + IMX_CCM_PLL_VIDEO_CTRL_REG PllVideoCtrlReg; > + IMX_CCM_PLL_VIDEO_CTRL_REG PllVideoCtrlSetReg; > + > + // Use clock rate as Denom for simple fractional calculation > + Denom = IMX_REF_CLK_24M_FREQ; > + DivSelect = ClockRate / IMX_REF_CLK_24M_FREQ; > + Numerator = ClockRate % IMX_REF_CLK_24M_FREQ; > + pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *)IMX_CCM_ANALOG_BASE; > + PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO); > + > + ASSERT (Numerator < Denom); > + ASSERT ((DivSelect >= 27) && (DivSelect <= 54)); > + > + // PLL output frequency = Fref * (DIV_SELECT + NUM / DENOM) > + PllVideoCtrlReg.DIV_SELECT = DivSelect; > + PllVideoCtrlReg.POST_DIV_SELECT = PostDivSelect; > + > + MmioWrite32 ( > + (UINTN)&pCcmAnalogRegisters->PLL_VIDEO, PllVideoCtrlReg.AsUint32); > + MmioWrite32 ( > + (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_NUM, Numerator); > + MmioWrite32 ( > + (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_DENOM, Denom); > + > + PllVideoCtrlReg.AsUint32 = MmioRead32 ( > + (UINTN)&pCcmAnalogRegisters->PLL_VIDEO); > + > + // Check to see if pll is locked, if not attempt to enable it > + if (PllVideoCtrlReg.LOCK == 0) { > + PllVideoCtrlClearReg.AsUint32 = 0; > + PllVideoCtrlClearReg.POWERDOWN = 1; > + MmioWrite32 ( > + (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_CLR, > + PllVideoCtrlClearReg.AsUint32); > + PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO); > + > + PllVideoCtrlSetReg.AsUint32 = 0; > + PllVideoCtrlSetReg.ENABLE = 1; > + MmioWrite32 ( > + (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_SET, > + PllVideoCtrlSetReg.AsUint32); > + PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO); > + > + PllVideoCtrlClearReg.AsUint32 = 0; > + PllVideoCtrlClearReg.BYPASS = 1; > + MmioWrite32 ( > + (UINTN)&pCcmAnalogRegisters->PLL_VIDEO_CLR, > + PllVideoCtrlClearReg.AsUint32); > + PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO); > + > + for (Counter = 0; Counter < 10000; Counter++) { > + PllVideoCtrlReg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_VIDEO); > + if (PllVideoCtrlReg.LOCK == 1) { > + DEBUG ((DEBUG_VERBOSE, "%a: PLL5 Video locked.\n", __FUNCTION__)); > + break; > + } > + } > + if (PllVideoCtrlReg.LOCK == 0) { > + DEBUG ((DEBUG_ERROR, "%a: PLL5 Video not locked.\n", __FUNCTION__)); > + } > + } > +} > + > +EFI_STATUS > +ImxpGetPll2PfdClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + IN IMX_PLL_PFD PfdIndex, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_ANALOG_REGISTERS *pCcmAnalogRegisters; > + IMX_CLOCK_INFO ParentInfo; > + IMX_CCM_PFD_528_REG Pfd528Reg; > + UINT32 PfdFrac; Fraction? > + EFI_STATUS Status; > + > + pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE; > + Pfd528Reg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PFD_528); > + switch (PfdIndex) { > + case IMX_PLL_PFD0: > + PfdFrac = Pfd528Reg.PFD0_FRAC; > + break; > + case IMX_PLL_PFD1: > + PfdFrac = Pfd528Reg.PFD1_FRAC; > + break; > + case IMX_PLL_PFD2: > + PfdFrac = Pfd528Reg.PFD2_FRAC; > + break; > + default: > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = ImxpGetClockInfo (Cache, IMX_PLL2_MAIN_CLK, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // The resulting frequency shall be 528*18/PFDn_FRAC > + // where PFD0_FRAC is in the range 12-35. > + ASSERT ((PfdFrac >= 12) && (PfdFrac <= 35)); > + ClockInfo->Frequency = (UINT32) ((UINT64) ParentInfo.Frequency * 18 / PfdFrac); > + ClockInfo->Parent = IMX_PLL2_MAIN_CLK; > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetAxiClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCDR_REG CbcdrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR); > + > + if (CbcdrReg.axi_sel == IMX_CCM_AXI_SEL_PERIPH_CLK) { > + Parent = IMX_PERIPH_CLK; > + } else { > + ASSERT (CbcdrReg.axi_sel == IMX_CCM_AXI_SEL_AXI_ALT); > + Parent = IMX_AXI_ALT; > + } > + > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.axi_podf); > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetGpu2dCoreClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCMR_REG CbcmrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR); > + switch (CbcmrReg.gpu2d_core_clk_sel) { > + case IMX_CCM_GPU2D_CORE_CLK_SEL_AXI: > + Parent = IMX_AXI_CLK_ROOT; > + break; > + case IMX_CCM_GPU2D_CORE_CLK_SEL_PLL3_SW: > + Parent = IMX_PLL3_SW_CLK; > + break; > + case IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD0: > + Parent = IMX_PLL2_PFD0; > + break; > + case IMX_CCM_GPU2D_CORE_CLK_SEL_PLL2_PFD2: > + Parent = IMX_PLL2_PFD2; > + break; > + default: > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcmrReg.gpu2d_core_clk_podf); > + ClockInfo->Parent = Parent; > + if (ClockInfo->Frequency > IMX_GPU2D_CORE_CLK_MAX) { > + DEBUG (( > + DEBUG_WARN, > + "%a: GPU2D_CORE_CLK exceeds maximum. (Value = %d, Max = %d)\n", > + __FUNCTION__, > + ClockInfo->Frequency, > + IMX_GPU2D_CORE_CLK_MAX)); > + } > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetGpu3dCoreClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCMR_REG CbcmrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR); > + switch (CbcmrReg.gpu3d_core_clk_sel) { > + case IMX_CCM_GPU3D_CORE_CLK_SEL_MMDC_CH0_AXI: > + Parent = IMX_MMDC_CH0_CLK_ROOT; > + break; > + case IMX_CCM_GPU3D_CORE_CLK_SEL_PLL3_SW: > + Parent = IMX_PLL3_SW_CLK; > + break; > + case IMX_CCM_GPU3D_CORE_CLK_SEL_PLL2_PFD1: > + Parent = IMX_PLL2_PFD1; > + break; > + case IMX_CCM_GPU3D_CORE_CLK_SEL_PLL2_PFD2: > + Parent = IMX_PLL2_PFD2; > + break; > + default: > + ASSERT (FALSE); > + return EFI_UNSUPPORTED; > + } > + > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcmrReg.gpu3d_core_podf); > + ClockInfo->Parent = Parent; > + if (ClockInfo->Frequency > IMX_GPU3D_CORE_CLK_MAX) { > + DEBUG (( > + DEBUG_WARN, > + "%a: GPU3D_CORE_CLK exceeds maximum. (Value = %d, Max = %d)\n", > + __FUNCTION__, > + ClockInfo->Frequency, > + IMX_GPU3D_CORE_CLK_MAX)); > + } > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetGpu3dShaderClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCMR_REG CbcmrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR); > + switch (CbcmrReg.gpu3d_shader_clk_sel) { > + case IMX_CCM_GPU3D_SHADER_CLK_SEL_MMDC_CH0_AXI: > + Parent = IMX_MMDC_CH0_CLK_ROOT; > + break; > + case IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL3_SW: > + Parent = IMX_PLL3_SW_CLK; > + break; > + case IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL2_PFD1: > + Parent = IMX_PLL2_PFD1; > + break; > + case IMX_CCM_GPU3D_SHADER_CLK_SEL_PLL3_PFD0: > + Parent = IMX_PLL3_PFD0; > + break; > + default: > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcmrReg.gpu3d_shader_podf); > + ClockInfo->Parent = Parent; > + > +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) > + if (ClockInfo->Frequency > IMX_GPU3D_SHADER_CLK_MAX) { > + DEBUG (( > + DEBUG_WARN, > + "%a: GPU3D_SHADER_CLK exceeds maximum. (Value = %d, Max = %d)", > + __FUNCTION__, > + ClockInfo->Frequency, > + IMX_GPU3D_SHADER_CLK_MAX)); > + } > +#endif > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetPeriphClk2Info ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCDR_REG CbcdrReg; > + IMX_CCM_CBCMR_REG CbcmrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR); > + switch (CbcmrReg.periph_clk2_sel) { > + case IMX_CCM_PERIPH_CLK2_SEL_PLL3_SW_CLK: > + Parent = IMX_PLL3_SW_CLK; > + break; > + case IMX_CCM_PERIPH_CLK2_SEL_OSC_CLK: > + Parent = IMX_OSC_CLK; > + break; > + case IMX_CCM_PERIPH_CLK2_SEL_PLL2: > + Parent = IMX_PLL2_MAIN_CLK; > + break; > + default: > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR); > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.periph_clk2_podf); > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetPeriphClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCDR_REG CbcdrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR); > + > + // NOTE: periph_clk_sel is OR'd with PLL_bypass_en2 (from jtag) to > + // produce the input value to the MUX. We assume PLL_bypass_en2 is 0. > + if (CbcdrReg.periph_clk_sel == 0) { > + Parent = IMX_PRE_PERIPH_CLK; > + } else { > + ASSERT (CbcdrReg.periph_clk_sel == 1); > + Parent = IMX_PERIPH_CLK2; > + } > + > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.mmdc_ch0_axi_podf); > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetMmdcCh0ClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCDR_REG CbcdrReg; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + Status = ImxpGetClockInfo (Cache, IMX_PERIPH_CLK, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR); > + ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.mmdc_ch0_axi_podf); > + ClockInfo->Parent = IMX_PERIPH_CLK; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetGpu2dAxiClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCMR_REG CbcmrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR); > + if (CbcmrReg.gpu2d_axi_clk_sel == IMX_CCM_GPU2D_AXI_CLK_SEL_AXI) { > + Parent = IMX_AXI_CLK_ROOT; > + } else { > + ASSERT (CbcmrReg.gpu2d_axi_clk_sel == IMX_CCM_GPU2D_AXI_CLK_SEL_AHB); > + Parent = IMX_AHB_CLK_ROOT; > + } > + > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ClockInfo->Frequency = ParentInfo.Frequency; > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetGpu3dAxiClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCMR_REG CbcmrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR); > + if (CbcmrReg.gpu3d_axi_clk_sel == IMX_CCM_GPU3D_AXI_CLK_SEL_AXI) { > + Parent = IMX_AXI_CLK_ROOT; > + } else { > + ASSERT (CbcmrReg.gpu3d_axi_clk_sel == IMX_CCM_GPU3D_AXI_CLK_SEL_AHB); > + Parent = IMX_AHB_CLK_ROOT; > + } > + > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ClockInfo->Frequency = ParentInfo.Frequency; > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +VOID > +ImxEnableGpuVpuPowerDomain ( > + VOID > + ) > +{ > + volatile IMX_CCM_ANALOG_REGISTERS *pAnalogRegisters; > + volatile IMX_GPC_REGISTERS *pGpcRegisters; > + volatile IMX_GPC_PGC_REGISTERS *pGpuPgcRegisters; > + IMX_GPC_CNTR_REG GpcCntrReg; > + IMX_PMU_REG_CORE_REG PmuCoreReg; > + IMX_GPC_PGC_PUPSCR_REG PupscrReg; > + > + pAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE; > + pGpcRegisters = (IMX_GPC_REGISTERS *) IMX_GPC_BASE; > + pGpuPgcRegisters = &pGpcRegisters->PGC_GPU; > + > + // Configure GPC/PGC PUPSCR Register SW2ISO bits > + PupscrReg.AsUint32 = MmioRead32 ((UINTN) &pGpuPgcRegisters->PUPSCR); > + PupscrReg.SW = IMX_GPC_PGC_PUPSCR_SW_DEFAULT; > + PupscrReg.SW2ISO = IMX_GPC_PGC_PUPSCR_SW2ISO_DEFAULT; > + MmioWrite32 ((UINTN) &pGpuPgcRegisters->PUPSCR, PupscrReg.AsUint32); > + > + // Turn on LDO_PU to 1.250V > + PmuCoreReg.AsUint32 = 0; > + PmuCoreReg.REG1_TARG = 0x1f; > + MmioWrite32 ((UINTN) &pAnalogRegisters->PMU_REG_CORE_CLR, PmuCoreReg.AsUint32); > + PmuCoreReg.REG1_TARG = 22; > + MmioWrite32 ((UINTN) &pAnalogRegisters->PMU_REG_CORE_SET, PmuCoreReg.AsUint32); > + MicroSecondDelay (100); > + > + // Assert power up request > + GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR); > + GpcCntrReg.gpu_vpu_pdn_req = 0; > + GpcCntrReg.gpu_vpu_pup_req = 1; > + MmioWrite32 ((UINTN) &pGpcRegisters->CNTR, GpcCntrReg.AsUint32); > + > + // Wait for power up request to complete > + do { > + GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR); > + } while (GpcCntrReg.gpu_vpu_pup_req != 0); > +} > + > +VOID > +ImxDisableGpuVpuPowerDomain ( > + VOID > + ) > +{ > + volatile IMX_GPC_REGISTERS *pGpcRegisters; > + volatile IMX_GPC_PGC_REGISTERS *pGpuPgcRegisters; > + IMX_GPC_PGC_PGCR_REG CtrlReg; > + IMX_GPC_CNTR_REG GpcCntrReg; > + IMX_GPC_PGC_PDNSCR_REG PdnscrReg; > + > + pGpcRegisters = (IMX_GPC_REGISTERS *) IMX_GPC_BASE; > + pGpuPgcRegisters = &pGpcRegisters->PGC_GPU; > + > + // Configure GPC/PGC PDNSCR Register ISO bits > + PdnscrReg.AsUint32 = MmioRead32 ((UINTN) &pGpuPgcRegisters->PDNSCR); > + PdnscrReg.ISO = IMX_GPC_PGC_PDNSCR_ISO_DEFAULT; > + PdnscrReg.ISO2SW = IMX_GPC_PGC_PDNSCR_ISO2SW_DEFAULT; > + MmioWrite32 ((UINTN) &pGpuPgcRegisters->PDNSCR, PdnscrReg.AsUint32); > + > + // Configure GPC/PGC CTRL[PCR] bit to allow power down of the blocks > + CtrlReg.AsUint32 = MmioRead32 ((UINTN) &pGpuPgcRegisters->CTRL); > + CtrlReg.PCR = 1; // Enable powering down of the blocks > + MmioWrite32 ((UINTN) &pGpuPgcRegisters->CTRL, CtrlReg.AsUint32); > + > + // Assert power down request > + GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR); > + GpcCntrReg.gpu_vpu_pdn_req = 1; > + GpcCntrReg.gpu_vpu_pup_req = 0; > + MmioWrite32 ((UINTN) &pGpcRegisters->CNTR, GpcCntrReg.AsUint32); > + > + // Wait for power down request to complete > + do { > + GpcCntrReg.AsUint32 = MmioRead32 ((UINTN) &pGpcRegisters->CNTR); > + } while (GpcCntrReg.gpu_vpu_pdn_req != 0); > +} > + > +EFI_STATUS > +ImxpGetClockInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + IN IMX_CLK ClockId, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + UINTN CacheValidBits; > + EFI_STATUS Status; > + > + ASSERT (ClockId < ARRAYSIZE (Cache->Table)); > + > + // First try to satisfy from cache > + CacheValidBits = Cache->Valid[ClockId / _BITS_PER_UINTN]; > + if (CacheValidBits & (1 << (ClockId % _BITS_PER_UINTN))) { > + *ClockInfo = Cache->Table[ClockId]; > + return EFI_SUCCESS; > + } Is this cache the purpose of this function? If so, are these really called repeatedly often enough to motivate this level of added complexity? > + > + switch (ClockId) { > + case IMX_OSC_CLK: > + ImxpGetOsc24ClkInfo (ClockInfo); > + Status = EFI_SUCCESS; > + break; > + case IMX_PLL1_MAIN_CLK: > + Status = ImxpGetPll1MainClkInfo (Cache, ClockInfo); > + break; > + case IMX_PLL2_MAIN_CLK: > + Status = ImxpGetPll2MainClkInfo (Cache, ClockInfo); > + break; > + case IMX_PLL2_PFD0: > + Status = ImxpGetPll2PfdClkInfo (Cache, IMX_PLL_PFD0, ClockInfo); > + break; > + case IMX_PLL2_PFD1: > + Status = ImxpGetPll2PfdClkInfo (Cache, IMX_PLL_PFD1, ClockInfo); > + break; > + case IMX_PLL2_PFD2: > + Status = ImxpGetPll2PfdClkInfo (Cache, IMX_PLL_PFD2, ClockInfo); > + break; > + case IMX_PLL3_MAIN_CLK: > + Status = ImxpGetPll3MainClkInfo (Cache, ClockInfo); > + break; > + case IMX_PLL3_PFD0: > + Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD0, ClockInfo); > + break; > + case IMX_PLL3_PFD1: > + Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD1, ClockInfo); > + break; > + case IMX_PLL3_PFD2: > + Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD2, ClockInfo); > + break; > + case IMX_PLL3_PFD3: > + Status = ImxpGetPll3PfdClkInfo (Cache, IMX_PLL_PFD3, ClockInfo); > + break; > + case IMX_PLL3_SW_CLK: > + Status = ImxpGetPll3SwClkInfo (Cache, ClockInfo); > + break; > + case IMX_AXI_CLK_ROOT: > + Status = ImxpGetAxiClkRootInfo (Cache, ClockInfo); > + break; > + case IMX_PERIPH_CLK2: > + Status = ImxpGetPeriphClk2Info (Cache, ClockInfo); > + break; > + case IMX_PERIPH_CLK: > + Status = ImxpGetPeriphClkInfo (Cache, ClockInfo); > + break; > + case IMX_PRE_PERIPH_CLK: > + Status = ImxpGetPrePeriphClkInfo (Cache, ClockInfo); > + break; > + case IMX_ARM_CLK_ROOT: > + Status = ImxpGetArmClkRootInfo (Cache, ClockInfo); > + break; > + case IMX_MMDC_CH0_CLK_ROOT: > + Status = ImxpGetMmdcCh0ClkRootInfo (Cache, ClockInfo); > + break; > + case IMX_AHB_CLK_ROOT: > + Status = ImxpGetAhbClkRootInfo (Cache, ClockInfo); > + break; > + case IMX_IPG_CLK_ROOT: > + Status = ImxpGetIpgClkRootInfo (Cache, ClockInfo); > + break; > + case IMX_GPU2D_AXI_CLK_ROOT: > + Status = ImxpGetGpu2dAxiClkRootInfo (Cache, ClockInfo); > + break; > + case IMX_GPU3D_AXI_CLK_ROOT: > + Status = ImxpGetGpu3dAxiClkRootInfo (Cache, ClockInfo); > + break; > + case IMX_GPU2D_CORE_CLK_ROOT: > + Status = ImxpGetGpu2dCoreClkInfo (Cache, ClockInfo); > + break; > + case IMX_GPU3D_CORE_CLK_ROOT: > + Status = ImxpGetGpu3dCoreClkInfo (Cache, ClockInfo); > + break; > + case IMX_GPU3D_SHADER_CLK_ROOT: > + Status = ImxpGetGpu3dShaderClkInfo (Cache, ClockInfo); > + break; > + default: > + return EFI_UNSUPPORTED; > + } > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Update the cache > + Cache->Table[ClockId] = *ClockInfo; > + Cache->Valid[ClockId / _BITS_PER_UINTN] |= (1 << (ClockId % _BITS_PER_UINTN)); > + return EFI_SUCCESS; > +} > + > +/** > + Power on and clock the GPU2D/GPU3D blocks. > + > + Follow the datasheet recommended sequence for clocking and powering: > + Gate clocks -> unpower module -> > + configure muxes/dividers -> power module -> Ungate clocks > +**/ > +EFI_STATUS > +ImxClkPwrGpuEnable ( > + VOID > + ) > +{ > +#if !defined(MDEPKG_NDEBUG) > + // Precondition: clock and power should be disabled > + ASSERT (ImxClkPwrGetClockGate (IMX_GPU3D_CLK_ENABLE) == IMX_CLOCK_GATE_STATE_OFF); > + ASSERT (ImxClkPwrGetClockGate (IMX_GPU2D_CLK_ENABLE) == IMX_CLOCK_GATE_STATE_OFF); > + ASSERT (ImxClkPwrGetClockGate (IMX_OPENVGAXICLK_CLK_ROOT_ENABLE) == IMX_CLOCK_GATE_STATE_OFF); I'm OK with the first two lines being slightly longer than 80 characters, but the third one really is too long. Wrap? > +#endif > + > + // Ensure clocks are gated > + ImxClkPwrSetClockGate (IMX_GPU3D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_OFF); > + ImxClkPwrSetClockGate (IMX_GPU2D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_OFF); > + ImxClkPwrSetClockGate (IMX_OPENVGAXICLK_CLK_ROOT_ENABLE, > + IMX_CLOCK_GATE_STATE_OFF); > + > + // Ensure GPU powered down (GPU should be powered down anyway) > + ImxDisableGpuVpuPowerDomain (); > + > + // Configure clock muxes and dividers for GPU3D, GPU2D, and OpenVG > + ImxCcmConfigureGpuClockTree (); > + > + // Power on the GPU > + ImxEnableGpuVpuPowerDomain (); > + > + // Ungate the GPU clocks > + ImxClkPwrSetClockGate (IMX_GPU3D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_ON); > + ImxClkPwrSetClockGate (IMX_GPU2D_CLK_ENABLE, IMX_CLOCK_GATE_STATE_ON); > + ImxClkPwrSetClockGate (IMX_OPENVGAXICLK_CLK_ROOT_ENABLE, > + IMX_CLOCK_GATE_STATE_ON); > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxClkPwrIpuDIxEnable ( > + VOID > + ) > +{ > + ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF); > + ImxClkPwrSetClockGate (IMX_IPU1_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF); > +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) > + ImxClkPwrSetClockGate (IMX_IPU2_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF); > + ImxClkPwrSetClockGate (IMX_IPU2_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF); > +#endif > + ImxCcmConfigureIPUDIxClockTree(); > + ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_ON); > + > + // Setup PLL to 65MHz as expected from UBOOT although transition > + // might be so fast that UBOOT screen would not be displayed ? > + ImxSetPll5ReferenceRate (65000000); > + return EFI_SUCCESS; > +} > + > +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) > +/** > + Setup the clock tree for LDB0/1 > +**/ > +EFI_STATUS > +ImxClkPwrIpuLDBxEnable ( > + VOID > + ) > +{ > + ImxClkPwrSetClockGate (IMX_LDB_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF); > + ImxClkPwrSetClockGate (IMX_LDB_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF); > + ImxCcmConfigureIPULDBxClockTree(); > + ImxClkPwrSetClockGate (IMX_LDB_DI0_CLK_ENABLE, IMX_CCM_CCGR_ON); > + ImxClkPwrSetClockGate (IMX_LDB_DI1_CLK_ENABLE, IMX_CCM_CCGR_ON); > + > + return EFI_SUCCESS; > +} > +#endif > + > +/** > + Configure PLL5 to the desired clock rate for all Display Interface (DI). > + Currently only support one display to IPU1 DI0. > +**/ > +EFI_STATUS > +ImxSetPll5ReferenceRate ( > + IN UINT32 ClockRate > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CHSCCDR_REG ChscddrReg; > + UINT32 DxPodfDivider; > + BOOLEAN FoundConfig; > + IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT postDivSelect[3]; p -> P > + UINT32 PostDivSelectCount; > + UINT32 PostDivSelectValue[3]; > + UINT32 TargetFreq; > + > + FoundConfig = FALSE; > + PostDivSelectValue[0] = 1; > + PostDivSelectValue[1] = 2; > + PostDivSelectValue[2] = 4; > + postDivSelect[0] = IMX_POST_DIV_SELECT_DIVIDE_1; > + postDivSelect[1] = IMX_POST_DIV_SELECT_DIVIDE_2; > + postDivSelect[2] = IMX_POST_DIV_SELECT_DIVIDE_4; > + > + for (PostDivSelectCount = 0; > + PostDivSelectCount < ARRAYSIZE (PostDivSelectValue); > + ++PostDivSelectCount) { > + for (DxPodfDivider = 1; DxPodfDivider < 9; ++DxPodfDivider) { > + TargetFreq = DxPodfDivider * ClockRate * PostDivSelectValue[PostDivSelectCount]; > + // The valid range for PPL loop divider is 27-54 so target freq needs > + // to fit within the valid range. > + if ((TargetFreq >= PLL5_MIN_FREQ) && > + (TargetFreq <= PLL5_MAX_FREQ)) { > + FoundConfig = TRUE; > + break; > + } > + } > + > + if (FoundConfig == TRUE) { > + break; > + } > + } > + > + if (FoundConfig == FALSE) { > + DEBUG ((DEBUG_ERROR, "%a: ClockRate %d\n", __FUNCTION__, ClockRate)); > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + DEBUG (( > + DEBUG_INFO, > + "%a: PLL 5 setting (%d) Target Freq %d Divider %d PostDiv %d\n", > + __FUNCTION__, > + ClockRate, > + TargetFreq, > + DxPodfDivider, > + PostDivSelectValue[PostDivSelectCount] > + )); > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + ChscddrReg.AsUint32 = MmioRead32 ((UINTN)&pCcmRegisters->CHSCCDR); > + ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF); > + ImxClkPwrSetClockGate (IMX_IPU1_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF); > +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) > + ImxClkPwrSetClockGate (IMX_IPU2_DI0_CLK_ENABLE, IMX_CCM_CCGR_OFF); > + ImxClkPwrSetClockGate (IMX_IPU2_DI1_CLK_ENABLE, IMX_CCM_CCGR_OFF); > +#endif > + ChscddrReg.ipu1_di0_podf = DxPodfDivider - 1; > + ChscddrReg.ipu1_di1_podf = DxPodfDivider - 1; > + MmioWrite32 ((UINTN)&pCcmRegisters->CHSCCDR, ChscddrReg.AsUint32); > + > + ImxClkPwrSetClockGate (IMX_IPU1_DI0_CLK_ENABLE, IMX_CCM_CCGR_ON); > + ImxSetClockRatePLL5 (TargetFreq, postDivSelect[PostDivSelectCount]); > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxClkPwrClkOut1Enable ( > + IN IMX_CLK Clock, > + IN UINT32 Divider > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CCOSR_REG CcosrReg; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + if ((Divider < 1) || (Divider > 8)) { > + return EFI_INVALID_PARAMETER; > + } > + > + CcosrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CCOSR); > + switch (Clock) { > + case IMX_OSC_CLK: > + CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_OSC_CLK; > + CcosrReg.CLKO2_DIV = Divider - 1; > + CcosrReg.CLKO2_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2; > + break; > + > + case IMX_PLL2_MAIN_CLK: > + CcosrReg.CLKO1_SEL = IMX_CCM_CLKO1_SEL_PLL2_MAIN_CLK_2; > + CcosrReg.CLKO1_DIV = Divider - 1; > + CcosrReg.CLKO1_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO1; > + break; > + > + case IMX_AXI_CLK_ROOT: > + CcosrReg.CLKO1_SEL = IMX_CCM_CLKO1_SEL_AXI_CLK_ROOT; > + CcosrReg.CLKO1_DIV = Divider - 1; > + CcosrReg.CLKO1_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO1; > + break; > + > + case IMX_IPG_CLK_ROOT: > + CcosrReg.CLKO1_SEL = IMX_CCM_CLKO1_SEL_IPG_CLK_ROOT; > + CcosrReg.CLKO1_DIV = Divider - 1; > + CcosrReg.CLKO1_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO1; > + break; > + > + case IMX_GPU2D_AXI_CLK_ROOT: > + CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU2D_AXI_CLK_ROOT; > + CcosrReg.CLKO2_DIV = Divider - 1; > + CcosrReg.CLKO2_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2; > + break; > + > + case IMX_GPU3D_AXI_CLK_ROOT: > + CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU3D_AXI_CLK_ROOT; > + CcosrReg.CLKO2_DIV = Divider - 1; > + CcosrReg.CLKO2_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2; > + break; > + > + case IMX_GPU2D_CORE_CLK_ROOT: > + CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU2D_CORE_CLK_ROOT; > + CcosrReg.CLKO2_DIV = Divider - 1; > + CcosrReg.CLKO2_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2; > + break; > + > + case IMX_GPU3D_CORE_CLK_ROOT: > + CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU3D_CORE_CLK_ROOT; > + CcosrReg.CLKO2_DIV = Divider - 1; > + CcosrReg.CLKO2_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2; > + break; > + > + case IMX_GPU3D_SHADER_CLK_ROOT: > + CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_GPU3D_SHADER_CLK_ROOT; > + CcosrReg.CLKO2_DIV = Divider - 1; > + CcosrReg.CLKO2_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2; > + break; > + > + case IMX_UART_CLK_ROOT: > + CcosrReg.CLKO2_SEL = IMX_CCM_CLKO2_SEL_UART_CLK_ROOT; > + CcosrReg.CLKO2_DIV = Divider - 1; > + CcosrReg.CLKO2_EN = 1; > + CcosrReg.CLK_OUT_SEL = IMX_CCM_CLK_OUT_SEL_CCM_CLKO2; > + break; > + > + default: > + return EFI_UNSUPPORTED; > + } > + > + MmioWrite32 ((UINTN) &pCcmRegisters->CCOSR, CcosrReg.AsUint32); > + return EFI_SUCCESS; > +} > + > +VOID > +ImxClkPwrClkOut1Disable ( > + VOID > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CCOSR_REG CcosrReg; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CcosrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CCOSR); > + CcosrReg.CLKO1_EN = 0; > + CcosrReg.CLKO2_EN = 0; > + MmioWrite32 ((UINTN) &pCcmRegisters->CCOSR, CcosrReg.AsUint32); > +} > + > +EFI_STATUS > +ImxClkPwrValidateClocks ( > + VOID > + ) > +{ > + IMX_CLOCK_INFO ActualInfo; > + UINT32 i; > + BOOLEAN Invalid; > + EFI_STATUS Status; > + > + Invalid = FALSE; > + for (i = 0; i < ARRAYSIZE (ExpectedClocks); ++i) { > + DEBUG (( > + DEBUG_INFO, > + "%a: Validating clock %s. Expecting: Frequency = %d (%d Mhz), Parent = %s\n", > + __FUNCTION__, > + StringFromImxClk (ExpectedClocks[i].Clock), > + ExpectedClocks[i].Info.Frequency, > + ExpectedClocks[i].Info.Frequency / 1000000, > + StringFromImxClk (ExpectedClocks[i].Info.Parent) > + )); > + Status = ImxClkPwrGetClockInfo (ExpectedClocks[i].Clock, &ActualInfo); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "%a: Failed to get clock info. (Clock = %s, Status = 0x%x)\n", > + __FUNCTION__, > + StringFromImxClk (ExpectedClocks[i].Clock), > + Status > + )); > + return Status; > + } > + if ((ActualInfo.Frequency != ExpectedClocks[i].Info.Frequency) || > + (ActualInfo.Parent != ExpectedClocks[i].Info.Parent)) { > + DEBUG (( > + DEBUG_ERROR, > + "%a: Clock settings do not match expected! Clock = %s (Expected, Actual) " > + "Frequency: %d, %d. Parent: %s, %s\n", > + __FUNCTION__, > + StringFromImxClk (ExpectedClocks[i].Clock), > + ExpectedClocks[i].Info.Frequency, > + ActualInfo.Frequency, > + StringFromImxClk (ExpectedClocks[i].Info.Parent), > + StringFromImxClk (ActualInfo.Parent) > + )); > + Invalid = TRUE; > + } > + } > + > + return Invalid ? EFI_DEVICE_ERROR : EFI_SUCCESS; > +} > + > +/** > + Reset/invalidate the clock tree cache. > + > + The clock tree cache must be invalidated whenever the clock tree is modified, > + e.g. when changing PLL configuration, clock mux, or divider. > + > +**/ > +VOID > +ImxpClkPwrCacheReset ( > + VOID > + ) > +{ > + SetMem (&mImxpClockPwrCache.Valid, sizeof (mImxpClockPwrCache.Valid), 0); > +} > + > +/** > + Configure clock gating for the specified clock signal. > + > + @param[in] ClockGate Specific clock signal to configure. > + @param[in] State State to set the clock signal to. > +**/ > +VOID > +ImxClkPwrSetClockGate ( > + IN IMX_CLK_GATE ClockGate, > + IN IMX_CLOCK_GATE_STATE State > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + UINTN EndBit; > + IMX_CCGR_INDEX Index; > + UINTN StartBit; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; (No space after '('). > + > + // Extract register index > + Index = ImxpCcgrIndexFromClkGate (ClockGate); > + StartBit = Index.GateNumber * 2; > + EndBit = StartBit + 1; > + > + MmioBitFieldWrite32 ( > + (UINTN) &pCcmRegisters->CCGR[Index.RegisterIndex], > + StartBit, > + EndBit, > + State); > +} > + > +/** > + Determine if gating TZASC1_IPG_MASTER_CLK should be skipped. > + **/ > +BOOLEAN > +ImxClkPwrShouldSkipTZASC1 ( > + VOID > + ) > +{ > +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) > + IMX_IOMUXC_GPR_REGISTERS *IoMuxMmioBasePtr; > + UINTN IomuxGPR9; > +#endif Could we break this block up a bit with a blank line please? > + BOOLEAN Skip; > + > + Skip = FALSE; And again, blank line? > +#if defined(CPU_IMX6DQ) || defined(CPU_IMX6DQP) > + IoMuxMmioBasePtr = (IMX_IOMUXC_GPR_REGISTERS *)IOMUXC_GPR_BASE_ADDRESS; > + > + IomuxGPR9 = MmioRead32 ((UINTN) &IoMuxMmioBasePtr->GPR9); > + if (IomuxGPR9 & IMX_IOMUXC_TZASC1_BYP) { > + // TZASC-1 is active. > + Skip = TRUE; > + } > +#endif > + > + return Skip; > +} > + > +/** > + Determine if a clock gate should be skipped > + > + @param[in] ClockGate Specific clock signal to configure. > + **/ > +BOOLEAN > +ImxClkPwrShouldSkipGate ( > + IN IMX_CLK_GATE ClockGate > + ) > +{ > + switch (ClockGate) { > + case IMX_IPSYNC_IP2APB_TZASC1_IPG_MASTER_CLK_ENABLE: > + return ImxClkPwrShouldSkipTZASC1 (); > + > + default: > + return FALSE; > + } > +} > + > +/** > + Set multiple clock signals to a given state. > + > + @param[in] ClockGateList Pointer to list of possible clock signals. > + @param[in] ClockGateCount Number of clock signals to gate. > + @param[in] State State to set the clock signal to. > +**/ > +VOID > +ImxClkPwrSetClockGates ( > + CONST IMX_CLK_GATE *ClockGateList, > + UINTN ClockGateCount, > + IMX_CLOCK_GATE_STATE State > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + UINTN i; > + IMX_CCGR_INDEX Index; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + > + // Read all CCGR registers to local copy > + UINT32 ccgrRegisters[ARRAYSIZE (pCcmRegisters->CCGR)]; > + for (i = 0; i < ARRAYSIZE (ccgrRegisters); ++i) { > + ccgrRegisters[i] = MmioRead32 ((UINTN) &pCcmRegisters->CCGR[i]); > + } > + > + // Compute new CCGR register values > + for (i = 0; i < ClockGateCount; ++i) { > + if (ImxClkPwrShouldSkipGate (ClockGateList[i])) { > + continue; > + } > + > + Index = ImxpCcgrIndexFromClkGate (ClockGateList[i]); > + ccgrRegisters[Index.RegisterIndex] = > + (ccgrRegisters[Index.RegisterIndex] & ~(0x3 << (2 * Index.GateNumber))) | > + (State << (2 * Index.GateNumber)); > + } > + > + // Write back to registers > + for (i = 0; i < ARRAYSIZE (ccgrRegisters); ++i) { > + MmioWrite32 ((UINTN) &pCcmRegisters->CCGR[i], ccgrRegisters[i]); > + } > +} > + > +/** > + Get the current clock gating setting for the specified clock gate. > + > + @param[in] ClockGate Specific clock signal to fetch clock gate info from. > +**/ > +IMX_CLOCK_GATE_STATE > +ImxClkPwrGetClockGate ( > + IN IMX_CLK_GATE ClockGate > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + UINTN EndBit; > + IMX_CCGR_INDEX Index; > + UINTN StartBit; > + UINT32 Value; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + Index = ImxpCcgrIndexFromClkGate (ClockGate); > + StartBit = Index.GateNumber * 2; > + EndBit = StartBit + 1; > + > + Value = MmioBitFieldRead32 ( > + (UINTN) &pCcmRegisters->CCGR[Index.RegisterIndex], > + StartBit, > + EndBit); > + > + if ((Value != IMX_CCM_CCGR_OFF) && > + (Value != IMX_CCM_CCGR_ON_RUN) && > + (Value != IMX_CCM_CCGR_ON)) { > + ASSERT (FALSE); > + } > + > + return (IMX_CLOCK_GATE_STATE) Value; > +} > + > +EFI_STATUS > +ImxpGetPll3MainClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_ANALOG_REGISTERS *pCcmAnalogRegisters; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + IMX_CCM_ANALOG_PLL_USB1_REG PllUsb1Reg; > + EFI_STATUS Status; > + > + pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE; > + PllUsb1Reg.AsUint32 = MmioRead32 ((UINTN)&pCcmAnalogRegisters->PLL_USB1); > + Parent = ImxpClkFromBypassClkSource (PllUsb1Reg.BYPASS_CLK_SRC); Add blank line? > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (PllUsb1Reg.DIV_SELECT == 0) { > + ClockInfo->Frequency = ParentInfo.Frequency * 20; > + } else { > + ClockInfo->Frequency = ParentInfo.Frequency * 22; Why the 20/22? A comment here would be useful. > + } > + > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetPll3PfdClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + IN IMX_PLL_PFD PfdIndex, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_ANALOG_REGISTERS *pCcmAnalogRegisters; > + IMX_CLOCK_INFO ParentInfo; > + IMX_CCM_PFD_480_REG Pfd480Reg; > + UINT32 PfdFrac; > + EFI_STATUS Status; > + > + pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE; > + Pfd480Reg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PFD_480); No space after ) when casting. > + switch (PfdIndex) { > + case IMX_PLL_PFD0: > + PfdFrac = Pfd480Reg.PFD0_FRAC; > + break; > + case IMX_PLL_PFD1: > + PfdFrac = Pfd480Reg.PFD1_FRAC; > + break; > + case IMX_PLL_PFD2: > + PfdFrac = Pfd480Reg.PFD2_FRAC; > + break; > + case IMX_PLL_PFD3: > + PfdFrac = Pfd480Reg.PFD3_FRAC; > + break; > + default: > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = ImxpGetClockInfo (Cache, IMX_PLL3_MAIN_CLK, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // The resulting frequency shall be 480*18/PFDn_FRAC What exactly does 480 mean here? > + // where PFD0_FRAC is in the range 12-35. > + ASSERT ((PfdFrac >= 12) && (PfdFrac <= 35)); > + ClockInfo->Frequency = (UINT32) ((UINT64) ParentInfo.Frequency * 18 / PfdFrac); No space after ) when casting. I think that 18 could to with a #define. > + ClockInfo->Parent = IMX_PLL3_MAIN_CLK; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetPll3SwClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CCSR_REG CcsrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CcsrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CCSR); > + if (CcsrReg.pll3_sw_clk_sel == IMX_CCM_PLL3_SW_CLK_SEL_PLL3_MAIN_CLK) { > + Parent = IMX_PLL3_MAIN_CLK; > + } else { > + ASSERT (CcsrReg.pll3_sw_clk_sel == IMX_CCM_PLL3_SW_CLK_SEL_PLL3_BYPASS_CLK); > + ASSERT (!"Not implemented"); > + return EFI_UNSUPPORTED; > + } > + > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ClockInfo->Frequency = ParentInfo.Frequency; > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetPll1MainClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_ANALOG_REGISTERS *pCcmAnalogRegisters; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + IMX_CCM_ANALOG_PLL_ARM_REG PllArmReg; > + EFI_STATUS Status; > + > + pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE; > + PllArmReg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PLL_ARM); > + Parent = ImxpClkFromBypassClkSource (PllArmReg.BYPASS_CLK_SRC); > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (PllArmReg.BYPASS != 0) { > + ClockInfo->Frequency = ParentInfo.Frequency; > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > + } > + > + ClockInfo->Frequency = (UINT32) ((UINT64) ParentInfo.Frequency * PllArmReg.DIV_SELECT / 2); > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetPll2MainClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_ANALOG_REGISTERS *pCcmAnalogRegisters; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + IMX_CCM_ANALOG_PLL_SYS_REG PllSysReg; > + EFI_STATUS Status; > + > + pCcmAnalogRegisters = (IMX_CCM_ANALOG_REGISTERS *) IMX_CCM_ANALOG_BASE; > + PllSysReg.AsUint32 = MmioRead32 ((UINTN) &pCcmAnalogRegisters->PLL_SYS); > + // Determine the reference clock source > + Parent = ImxpClkFromBypassClkSource (PllSysReg.BYPASS_CLK_SRC); Add blank line? > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (PllSysReg.BYPASS != 0) { > + ClockInfo->Frequency = ParentInfo.Frequency; > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > + } > + > + if (PllSysReg.DIV_SELECT == 0) { > + ClockInfo->Frequency = ParentInfo.Frequency * 20; > + } else { > + ASSERT (PllSysReg.DIV_SELECT == 1); > + ClockInfo->Frequency = ParentInfo.Frequency * 22; > + } This pattern seems to be repeating - add as helper function? > + > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetArmClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CACRR_REG CacrrReg; > + IMX_CLOCK_INFO Pll1Info; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + Status = ImxpGetClockInfo (Cache, IMX_PLL1_MAIN_CLK, &Pll1Info); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + CacrrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CACRR); > + ClockInfo->Frequency = Pll1Info.Frequency / (1 + CacrrReg.arm_podf); > + ClockInfo->Parent = IMX_PLL1_MAIN_CLK; > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetPrePeriphClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCMR_REG CbcmrReg; > + IMX_CLK Parent; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + CbcmrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCMR); Insert blank line? > + switch (CbcmrReg.pre_periph_clk_sel) { > + case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2: > + Parent = IMX_PLL2_MAIN_CLK; > + break; > + case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2: > + Parent = IMX_PLL2_PFD2; > + break; > + case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD0: > + Parent = IMX_PLL2_PFD0; > + break; > + case IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2_DIV2: > + Parent = IMX_PLL2_PFD2; > + break; > + default: > + ASSERT (FALSE); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = ImxpGetClockInfo (Cache, Parent, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + if (CbcmrReg.pre_periph_clk_sel == IMX_CCM_PRE_PERIPH_CLK_SEL_PLL2_PFD2_DIV2) { > + ClockInfo->Frequency = ParentInfo.Frequency / 2; > + } else { > + ClockInfo->Frequency = ParentInfo.Frequency; > + } > + > + ClockInfo->Parent = Parent; > + return EFI_SUCCESS; > +} > + > +VOID > +ImxpGetOsc24ClkInfo ( > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + ClockInfo->Frequency = IMX_REF_CLK_24M_FREQ; > + ClockInfo->Parent = IMX_CLK_NONE; > +} > + > +EFI_STATUS > +ImxpGetAhbClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCDR_REG CbcdrReg; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + Status = ImxpGetClockInfo (Cache, IMX_PERIPH_CLK, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR); > + ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.ahb_podf); > + ClockInfo->Parent = IMX_PERIPH_CLK; Insert blank line? > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxpGetIpgClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + volatile IMX_CCM_REGISTERS *pCcmRegisters; > + IMX_CCM_CBCDR_REG CbcdrReg; > + IMX_CLOCK_INFO ParentInfo; > + EFI_STATUS Status; > + > + pCcmRegisters = (IMX_CCM_REGISTERS *) IMX_CCM_BASE; > + Status = ImxpGetClockInfo (Cache, IMX_AHB_CLK_ROOT, &ParentInfo); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + CbcdrReg.AsUint32 = MmioRead32 ((UINTN) &pCcmRegisters->CBCDR); > + ClockInfo->Frequency = ParentInfo.Frequency / (1 + CbcdrReg.ipg_podf); > + ClockInfo->Parent = IMX_AHB_CLK_ROOT; Insert blank line? > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +ImxClkPwrGetClockInfo ( > + IN IMX_CLK ClockId, > + OUT IMX_CLOCK_INFO *ClockInfo > + ) > +{ > + return ImxpGetClockInfo (&mImxpClockPwrCache, ClockId, ClockInfo); > +} > diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf > new file mode 100644 > index 000000000000..5e4603131471 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwrLib.inf > @@ -0,0 +1,46 @@ > +## @file > +# > +# Copyright (c) 2018 Microsoft Corporation. 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. > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001A > + BASE_NAME = iMX6ClkPwrLib > + FILE_GUID = 8DB4B460-9201-435A-B86A-24B58CED9A9E > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = iMX6ClkPwrLib > + > +[Packages] > + ArmPkg/ArmPkg.dec > + ArmPlatformPkg/ArmPlatformPkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > + Silicon/NXP/iMX6Pkg/iMX6Pkg.dec > + Silicon/NXP/iMXPlatformPkg/iMXPlatformPkg.dec > + > +[LibraryClasses] > + BaseMemoryLib > + DebugLib > + iMXIoMuxLib > + IoLib > + TimerLib I am OK with these being sorted either case-sensitively or case-insensitively, as long as it's consistent (and I have seen both in this set). > + > +[Sources.common] > + iMX6ClkPwr.c > + > +[FeaturePcd] > + giMX6TokenSpaceGuid.PcdLvdsEnable > + > +[FixedPcd] > + giMXPlatformTokenSpaceGuid.PcdGpioBankMemoryRange > diff --git a/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h > new file mode 100644 > index 000000000000..2de1f62c7740 > --- /dev/null > +++ b/Silicon/NXP/iMX6Pkg/Library/iMX6ClkPwrLib/iMX6ClkPwr_private.h > @@ -0,0 +1,221 @@ > +/** @file > +* > +* Copyright (c) 2018 Microsoft Corporation. All rights reserved. > +* Copyright 2018 NXP > +* > +* 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. > +* > +**/ > + > +#ifndef _IMX6_CLK_PWR_PRIVATE_H_ > +#define _IMX6_CLK_PWR_PRIVATE_H_ > + > +#ifndef ARRAYSIZE > +#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) > +#endif // ARRAYSIZE Please use Base.h ARRAY_SIZE macro instead. > + > +#define _BITS_PER_UINTN (8 * sizeof(UINTN)) No _ in macro names, please. Space between sizeof and '('. / Leif > + > +typedef enum { > + IMX_PLL_PFD0, > + IMX_PLL_PFD1, > + IMX_PLL_PFD2, > + IMX_PLL_PFD3, > +} IMX_PLL_PFD; > + > +typedef struct { > + IMX_CLK Clock; > + IMX_CLOCK_INFO Info; > +} IMX_CLOCK_CONTEXT; > + > +typedef struct { > + UINT16 RegisterIndex; // Register index (0-6) > + UINT16 GateNumber; // Gate number within register (0-15) > +} IMX_CCGR_INDEX; > + > +typedef struct { > + UINTN Valid[(IMX_CLK_MAX + _BITS_PER_UINTN) / _BITS_PER_UINTN]; > + IMX_CLOCK_INFO Table[IMX_CLK_MAX]; > +} IMX_CLOCK_TREE_CACHE; > + > +IMX_CCGR_INDEX > +ImxpCcgrIndexFromClkGate ( > + IN IMX_CLK_GATE ClockGate > + ); > + > +VOID > +ImxpClkPwrCacheReset ( > + VOID > + ); > + > +IMX_CLK > +ImxpClkFromBypassClkSource ( > + IN IMX_PLL_BYPASS_CLK_SRC BypassClockSource > + ); > + > +VOID > +ImxCcmConfigureGpuClockTree ( > + VOID > + ); > + > +VOID > +ImxCcmConfigureIPUDIxClockTree ( > + VOID > + ); > + > +VOID > +ImxCcmConfigureIPULDBxClockTree ( > + VOID > + ); > + > +VOID > +ImxSetClockRatePLL5 ( > + IN UINT32 ClockRate, > + IN IMX_CCM_PLL_VIDEO_CTRL_POST_DIV_SELECT PostDivSelect > + ); > + > +EFI_STATUS > +ImxpGetClockInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + IN IMX_CLK ClockId, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +VOID > +ImxpGetOsc24ClkInfo ( > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetPll1MainClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetPll2MainClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetPll2PfdClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + IN IMX_PLL_PFD PfdIndex, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetPll3MainClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetPll3PfdClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + IN IMX_PLL_PFD PfdIndex, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetPll3SwClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetAxiClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetPeriphClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetPrePeriphClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetPeriphClk2Info ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetArmClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetMmdcCh0ClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetAhbClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetIpgClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetGpu2dAxiClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetGpu3dAxiClkRootInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetGpu2dCoreClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetGpu3dCoreClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +EFI_STATUS > +ImxpGetGpu3dShaderClkInfo ( > + IN OUT IMX_CLOCK_TREE_CACHE *Cache, > + OUT IMX_CLOCK_INFO *ClockInfo > + ); > + > +VOID > +ImxEnableGpuVpuPowerDomain ( > + VOID > + ); > + > +VOID > +ImxDisableGpuVpuPowerDomain ( > + VOID > + ); > + > +#endif // _IMX6_CLK_PWR_PRIVATE_H_ > -- > 2.16.2.gvfs.1.33.gf5370f1 >