From patchwork Mon May 28 12:25:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peng Fan X-Patchwork-Id: 921500 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=nxp.com header.i=@nxp.com header.b="Zn0Oe+SC"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40vbtd43Hrz9s0q for ; Mon, 28 May 2018 22:35:53 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 3893BC21DFD; Mon, 28 May 2018 12:26:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=BAD_ENC_HEADER, RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id DB31CC21E5B; Mon, 28 May 2018 12:23:06 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 6A611C21E1A; Mon, 28 May 2018 12:22:35 +0000 (UTC) Received: from EUR03-DB5-obe.outbound.protection.outlook.com (mail-eopbgr40071.outbound.protection.outlook.com [40.107.4.71]) by lists.denx.de (Postfix) with ESMTPS id D6927C21E4E for ; Mon, 28 May 2018 12:22:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=icQJFWKNUKjpoxtLsofkxPt/MSxbz193VLEfvxpxaKA=; b=Zn0Oe+SCCAcdeL9aqDmEcg0fObXopmzOR6ocvlTqJfERlK4Bn0d2NnbrF1d136yri5mVbFXPFReU/RhQ0hJNQBtRzQGxTZIcKfDViLXQN15IlkWhNovNgP/XCi5foDCneiyx8UgsmwqXQn19kZOfn/rlNsd53rPW0fz8f7/szy0= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=peng.fan@nxp.com; Received: from linux-u7w5.ap.freescale.net.net (92.121.68.129) by VI1PR04MB3006.eurprd04.prod.outlook.com (2603:10a6:802:9::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.797.11; Mon, 28 May 2018 12:22:24 +0000 From: Peng Fan To: sbabic@denx.de, fabio.estevam@nxp.com Date: Mon, 28 May 2018 20:25:03 +0800 Message-Id: <20180528122526.20597-19-peng.fan@nxp.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180528122526.20597-1-peng.fan@nxp.com> References: <20180528122526.20597-1-peng.fan@nxp.com> MIME-Version: 1.0 X-Originating-IP: [92.121.68.129] X-ClientProxiedBy: HK2PR02CA0175.apcprd02.prod.outlook.com (2603:1096:201:21::11) To VI1PR04MB3006.eurprd04.prod.outlook.com (2603:10a6:802:9::12) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(5600026)(48565401081)(4534165)(4627221)(201703031133081)(201702281549075)(2017052603328)(7153060)(7193020); SRVR:VI1PR04MB3006; X-Microsoft-Exchange-Diagnostics: 1; VI1PR04MB3006; 3:pHW2uCbi7h/TPX6JwV/auMqBDXH+oCd9r+LtyWjkhlaoII9MfuHlQx5TdChD5xffcLUPUMpyi3CfImkLwNbaxd/Sbn4gM4hopdjXbDwycuQP1fS4eSCC/RcFIgn68CXf11HzXmYqY/Iei8txDYYri2D2P3yYO67r+UisiVtM0N7RmqZDUj3DzLpJBAJWDgAwn2iP3SQON8UAojb+UqTEk3lf3FHpt9CbyXVQ6rcJiBfpso+aUqyTlqkqIuLaPM0C; 25:07lL944AgzH/UvJgEHPaL2k1gHHDtTfjAAqs4Exd2HBV4VWiaPEQ+qbhKOjTmQscERw+MoQk4mpve/sf4+oyFgso7qB45magPvjv/MbXNK10Bl7iqK2/U2e+bnIZkboYlswl9fdbNRSQZPhwOFnWxXX0QDeI11d5ggt7jUK5dNcSKD7ejkMKrIcwD91gk8VUxNiIYBl4m37WOkNzxSbhL7bE17aW1hzp8UAGqrF/tdDX2og29rHtPkOcRdpY1AJAdkAU6K7oweAC4vy+wk8DJ0cIPsvbvavu68aPukyhRKOH9PmUJIH7Ke3+1CTgV3eE+cRGdIGv/LwJJUGZIRjVXQ==; 31:v/DgcHczRVcsEFdjOuwi2PEtlZSuN7TUyQeFOs2hzP2MnapC1Su2U/21sREuI6tcXarO6bLNom9XN291IVZ7+44V1sOZUm906TK8ERbk2+Yo0q0mgd8GUnCbVX26Ey/sh0B7sw58kyqSevXPkrTMrxhgTVmuxXedZidj29U3phnoUywESAPEJX47Q7G5Azdyi3v0VZRJZs2Zgi7Fsm3UUXMxziFIqoiNemtCxtbW9rg= X-MS-TrafficTypeDiagnostic: VI1PR04MB3006: X-Microsoft-Exchange-Diagnostics: 1; VI1PR04MB3006; 20:pRuYLlIgYiyaqFJd3gldRAjO6ZzwE6U+Zsvx6Uj/T69sI8u3gyJOFBOFyv5GnFSk7ePIhmzXabZcxWtcOTTJwSVN0kctPleGSWMvrpd3CpfAD1WIiHlri6CBxTIAv5AGJ0tVW2tX3NXJpwum7tfrJYQUhlbIx+RN/F5ghzHWO9O5ZN+AYYOUYTOhiBg/66Nu2/NdxY5bHUXLlGD0JpwjvqdlKlHZ9sdy+6O2Wjm7HriYqmfBxLLkHLYdJ+CwCfLsYSUUsmpDbPms+010RR6xS6Ny5vLHrF448EFxTeZlBZgqGBaR5ZeTlCIJr2LqaOtGJ9w5FTK9ZZwe8QvuRNlcgviHEeYm3RNl3CLIaiG1UEoT3/3s1luBdkxw4w5GYUBHeRQuOSgHuD9EhGhNY9hPhsdOScZIpGjwcBUmHcK8nzwVnMZwT8fgzBYDQIrI/AkzbN6S8sx1IxVkYBZJJaHcLPWHY79RKJ+TklhYKP6FOJscR4pvx0peJ3tMnqYD6VOU; 4:qudaADZLxLfoVuwybjyixNZoMbz8dnx2ZHAIU0zepBg3zAMlsP6iZ6SbUhJc6/K6769dIAIFvF+j0rB1CrscOa9ZbUXlOmmcccaYsAZcqWS4jVKyihYbsGMb4mTlNWvtgEi8d4mPR58Dc1zLOQTe6NH28YZwvc198sO32PoVTn4EXoEywcqXkBM3Z6Q/BwvL1aNdfjcUxruvHzFT/RyIKXH8W76axKJSC4/HTS6efLuczD1B9OcjHOOJKElFi0SXmgQWYBi5XAZPXNCiwJcD5vTKyTitw2ebs3MKYUBhJxAFHgvTmPBMzvxkchwt1Kb/ X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(3002001)(93006095)(93001095)(3231254)(944501410)(52105095)(10201501046)(6055026)(149027)(150027)(6041310)(20161123558120)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123562045)(20161123564045)(6072148)(201708071742011)(7699016); SRVR:VI1PR04MB3006; BCL:0; PCL:0; RULEID:; SRVR:VI1PR04MB3006; X-Forefront-PRVS: 06860EDC7B X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(366004)(39380400002)(396003)(39860400002)(376002)(346002)(199004)(189003)(36756003)(97736004)(6636002)(6666003)(68736007)(86362001)(8676002)(44832011)(8936002)(81166006)(81156014)(47776003)(11346002)(956004)(2616005)(476003)(446003)(25786009)(486006)(48376002)(106356001)(105586002)(186003)(50466002)(16526019)(2906002)(6512007)(53936002)(1076002)(59450400001)(66066001)(26005)(51416003)(478600001)(305945005)(50226002)(6486002)(5660300001)(6116002)(76176011)(3846002)(16586007)(52116002)(6506007)(4326008)(316002)(7736002)(386003); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR04MB3006; H:linux-u7w5.ap.freescale.net.net; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; Received-SPF: None (protection.outlook.com: nxp.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR04MB3006; 23:+UEMB5/hHtv/gBF5Zp67pL/lop5U8yV/X+ykQJph1?= /CzZGl3IXKTl5GdhH8acFQNAra5cR3oZluc1Y0mTWV0WaMffGq0CBfKF3xjMggFM5fSxn1osYbja2WKU4XvPgjhsI4mkev726WMxLWt7kZcHQs9AtCuxesP0boowRS8bi2NT3R7Gp/m6Hkrbv370ubjaFGodfCyPCXffIMA/tpDHUYtJNWkhB2+NUpWuOXy68Ik6attWtotqApxa6jGhDtSlRDaFdowxMQVuKKXsQO79ru11Uk63L9w9URK9/WwAyJ2md11AVUuPydhXxq02NJSNiOqWbLqhmz3sdGJN/aAJ/gvai7CW2vmWrFmPf19lmWTjrUO+CuptDnViewz8ZUDWIHUxeEdOXEvrauRZiYA6ehlobUH/vUA6Gve2UcJvBE0urzneTT4w4QL3PK0kWdvNc13qHtvpr4uWKnk5wvm0RYkwUHRSmzPxzbgWpUkuf8RUNV6f5/6opyPyuEW6KBVDxUrdlMgSGK4i4Gxyvntsk+/hMtLF5rCrbgMAFNP19egfpx6pSoGZUXMtKHxOSCFVGcyQPrHiiY5uRJepHx91DUGsTuIi9UgCSWNKc3Hf+kZKXQ7LloVHB/ALDaEu91X0TM05zrgzok/+KxmzwvE7qqqMiuPpg1myH3i7LcaYlRlfOQ6VGAFsN+R0np0PU2vKuownI4liHGCE3H2Gz5W3mkPfgFJh2XRIue30ph6ghsDaNnyrfJFIBkjIADUKJVEAneb/lrOYTA3POcNgxWjim3ZlSbvM6FuCfFU+p3RWtZ/+KPv6mGxvqvWSIWp6XMV3BRhJSOraDvVEfJiOet8Y8CZrquD6FnOLdh0kVEoIUrDVBf+Ff09eGIIOJw6azX82TiaaF1D94JqInTnJSztC8sDr/G3wwZn4NiPJmhNkY1WMQaOvw213k27/fzYgnQT6DX/cNqA2GgKol4hk9ykuxjyOU1N4sjMff4d8TEO0h+Q4QEVbsggBr3qnCohgdh6vYRZg+sFzMUTpli3dJFd3V+0eeyCbfhkS7Pret7/7blelA2rVHVQpPKteYgtm74SGI/uDOaZgm2QX6kXtDDkkMaPdTpkaGOUMRHJN/gWlWOKhgQkNJvHPEaD6k3QQAkzO0DaWetkOsDoo+ZpyxlXVXCXWWd8ey9IXtl8369iYuFX9vXIiH/dvKPxW+z2qeq/ffSBZsRKaQ6pY/eUejsvcKgsSJXAPxG4cprTGQYe/oc= X-Microsoft-Antispam-Message-Info: CPDgD/GJJ32du+PHMiS0EMtFFn1qlDFhrReEoE3j4Vr8rjdO8tEZU2LXH528O0kDfZkXQOWyn3CXx8NeKedR7nkjiYhWzSbr3J73TJRo2DHZnIaq+a9L70+OpuOznwmNYh9wH8oJeKnT2+L9UuHnA+Otke79O/Mbty4wqPcv4PRse16kHFTBXC7oZNKO+9Az X-Microsoft-Exchange-Diagnostics: 1; VI1PR04MB3006; 6:34htzTmAEn2NOKf8wHvfcyXrI0GBOoTvOBurpIDkAMEWZ1LT4TyPSMQzw1jiM+XI7sdpN6kVv9R0xd+MvYlGFc3PfX1niFqI4/CWQQG4Lnr5Jki7zykXMSl4T9WawmTm6DLb6nnc0tOtXoGkT6ELPQcmiLswR8sqREzsg0jTCjaJeRSZsOdidB5VzfqbAeVWZQPiVjo/Zo+Xsy+CE4SjKaMp4gDKCQLdYj/8Cb/LtUgmFMFUXGRY9+IJf6k+sblSLHM63Ret+XY+p6K6H4eTH9pSmtq8w7DDIiPOX9pPCXBriCuA07dWYY8TP9Wb8euVy0dPqccqhFF4MbPgJLgBrz4KW8LfRt+BzmWP+6GOmH+TBWSpopirw/wK45jqYkiQsxLJ+9wO2fyLADYit7etBAZb1Mv95rzniqdzrHAkKWma0nIkMd6bTZmeGO0lFFkLI38itfno8kuPP98zIP2DHQ==; 5:2hzqIXJ05Iv0d3Pn/B5tRg4sA+qyHxX3ByauC0gTfVPz12U1cEidNJ3wX8rIJdSKrECGafah6Lls2beUyyo9EqCT13Jyy6jXJ9ep3edZBfq1GvCeaLW/t4YoiTPs1zSGxkYuLrREdMpRbhpQaR9AoLuFT+WBlrzEHeKtVsL8YjA=; 24:4IlKW0dTEyFBW3qDBCaLsBrm5OAs+Bf05rQ2l/R4uQQNCXJ4v16pecSeMNU87oaNqvqP97HfFG8vk3Iaqb+i8IqI/xEMJ+tfBE1IQ1TRgks= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; VI1PR04MB3006; 7:x8Arz9hAz051UJkyMwFF5I1EDxcXjEH0CC0aHIPhdKSKcrYAh3aNo+urHo+wUYvGoLQ7ztiPXHZwWUGOBZF9pAUwKkIP2GG67WhlBYviNhEzBUof/t2G3AWHHlRHiaXurnA/xjDTMpsOvkCjozyBFQDq29f34FwcZN7d6nJpartgOc9lTuTEkxX6OgKf6R5hUgIbZVxHxImMqWI2zcONShDYxwlWoS63HGAWgjCDkTseIhfPh8iUYy5GgnId38xN X-MS-Office365-Filtering-Correlation-Id: d0535ae6-2acf-4d56-e385-08d5c495ac71 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 May 2018 12:22:24.5734 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d0535ae6-2acf-4d56-e385-08d5c495ac71 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR04MB3006 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH 18/41] imx8: add clock driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add clock driver for i.MX8, including get arm core clock, peripheral's clock, configure I2C/flexspi/enet/gpmi-nand/usb clock. Signed-off-by: Peng Fan --- arch/arm/include/asm/arch-imx8/clock.h | 36 ++++ arch/arm/include/asm/arch-imx8/i2c.h | 34 ++++ arch/arm/mach-imx/imx8/Makefile | 2 +- arch/arm/mach-imx/imx8/clock.c | 361 +++++++++++++++++++++++++++++++++ 4 files changed, 432 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/arch-imx8/clock.h create mode 100644 arch/arm/include/asm/arch-imx8/i2c.h create mode 100644 arch/arm/mach-imx/imx8/clock.c diff --git a/arch/arm/include/asm/arch-imx8/clock.h b/arch/arm/include/asm/arch-imx8/clock.h new file mode 100644 index 0000000000..ff98324b1c --- /dev/null +++ b/arch/arm/include/asm/arch-imx8/clock.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2018 NXP + */ + +#ifndef __ASM_ARCH_IMX8_CLOCK_H__ +#define __ASM_ARCH_IMX8_CLOCK_H__ + +/* Mainly for compatible to imx common code. */ +enum mxc_clock { + MXC_ARM_CLK = 0, + MXC_AHB_CLK, + MXC_IPG_CLK, + MXC_UART_CLK, + MXC_CSPI_CLK, + MXC_AXI_CLK, + MXC_DDR_CLK, + MXC_ESDHC_CLK, + MXC_ESDHC2_CLK, + MXC_ESDHC3_CLK, + MXC_I2C_CLK, + MXC_FEC_CLK, +}; + +u32 mxc_get_clock(enum mxc_clock clk); +u32 get_lpuart_clk(void); +int enable_i2c_clk(u8 enable, u32 i2c_num); +u32 imx_get_i2cclk(u32 i2c_num); +void enable_usboh3_clk(bool enable); +int set_clk_qspi(void); +u32 imx_get_fecclk(void); +void init_clk_usdhc(u32 index); +void init_clk_gpmi_nand(void); +void init_clk_usb3(int index); + +#endif /* __ASM_ARCH_IMX8_CLOCK_H__ */ diff --git a/arch/arm/include/asm/arch-imx8/i2c.h b/arch/arm/include/asm/arch-imx8/i2c.h new file mode 100644 index 0000000000..b20db5eb1e --- /dev/null +++ b/arch/arm/include/asm/arch-imx8/i2c.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2017 NXP + */ +#ifndef __ASM_ARCH_IMX8_I2C_H__ +#define __ASM_ARCH_IMX8_I2C_H__ + +#include + +struct imx_i2c_map { + int index; + sc_rsrc_t rsrc; +}; + +static struct imx_i2c_map imx_i2c_desc[] = { + {0, SC_R_I2C_0}, + {1, SC_R_I2C_1}, + {2, SC_R_I2C_2}, + {3, SC_R_I2C_3}, + {4, SC_R_I2C_4}, + {5, SC_R_LVDS_0_I2C_0}, /* lvds0 i2c0 */ + {6, SC_R_LVDS_0_I2C_0}, /* lvds0 i2c1 */ + {7, SC_R_LVDS_1_I2C_0}, /* lvds1 i2c0 */ + {8, SC_R_LVDS_1_I2C_0}, /* lvds1 i2c1 */ + {9, SC_R_CSI_0_I2C_0}, + {10, SC_R_CSI_1_I2C_0}, + {11, SC_R_HDMI_I2C_0}, + {12, SC_R_HDMI_RX_I2C_0}, + {13, SC_R_MIPI_0_I2C_0}, + {14, SC_R_MIPI_0_I2C_1}, + {15, SC_R_MIPI_1_I2C_0}, + {16, SC_R_MIPI_1_I2C_1}, +}; +#endif /* __ASM_ARCH_IMX8_I2C_H__ */ diff --git a/arch/arm/mach-imx/imx8/Makefile b/arch/arm/mach-imx/imx8/Makefile index 9545fd8d03..2921d18f9f 100644 --- a/arch/arm/mach-imx/imx8/Makefile +++ b/arch/arm/mach-imx/imx8/Makefile @@ -4,7 +4,7 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y += cpu.o +obj-y += cpu.o clock.o obj-y += fsl_mu_hal.o sci/ipc.o obj-y += sci/svc/misc/rpc_clnt.o obj-y += sci/svc/pad/rpc_clnt.o diff --git a/arch/arm/mach-imx/imx8/clock.c b/arch/arm/mach-imx/imx8/clock.c new file mode 100644 index 0000000000..a12bfea633 --- /dev/null +++ b/arch/arm/mach-imx/imx8/clock.c @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017-2018 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static u32 get_arm_main_clk(void) +{ + sc_err_t err; + sc_pm_clock_rate_t clkrate; + sc_ipc_t ipchandle = (sc_ipc_t)gd->arch.ipc_channel_handle; + + if (is_cortex_a35()) + err = sc_pm_get_clock_rate(ipchandle, SC_R_A35, SC_PM_CLK_CPU, + &clkrate); + else + err = SC_ERR_UNAVAILABLE; + + if (err != SC_ERR_NONE) { + printf("sc get ARM clk failed! err=%d\n", err); + return 0; + } + + return clkrate; +} + +u32 get_lpuart_clk(void) +{ + return mxc_get_clock(MXC_UART_CLK); +} + +u32 mxc_get_clock(enum mxc_clock clk) +{ + sc_err_t err; + sc_pm_clock_rate_t clkrate; + sc_ipc_t ipchandle = (sc_ipc_t)gd->arch.ipc_channel_handle; + + switch (clk) { + case MXC_UART_CLK: + err = sc_pm_get_clock_rate(ipchandle, SC_R_UART_0, 2, &clkrate); + if (err != SC_ERR_NONE) { + printf("sc get UART clk failed! err=%d\n", err); + return 0; + } + return clkrate; + case MXC_ESDHC_CLK: + err = sc_pm_get_clock_rate(ipchandle, SC_R_SDHC_0, 2, &clkrate); + if (err != SC_ERR_NONE) { + printf("sc get uSDHC1 clk failed! err=%d\n", err); + return 0; + } + return clkrate; + case MXC_ESDHC2_CLK: + err = sc_pm_get_clock_rate(ipchandle, SC_R_SDHC_1, 2, &clkrate); + if (err != SC_ERR_NONE) { + printf("sc get uSDHC2 clk failed! err=%d\n", err); + return 0; + } + return clkrate; + case MXC_ESDHC3_CLK: + err = sc_pm_get_clock_rate(ipchandle, SC_R_SDHC_2, 2, &clkrate); + if (err != SC_ERR_NONE) { + printf("sc get uSDHC3 clk failed! err=%d\n", err); + return 0; + } + return clkrate; + case MXC_FEC_CLK: + err = sc_pm_get_clock_rate(ipchandle, SC_R_ENET_0, 2, &clkrate); + if (err != SC_ERR_NONE) { + printf("sc get ENET clk failed! err=%d\n", err); + return 0; + } + return clkrate; + case MXC_ARM_CLK: + return get_arm_main_clk(); + default: + printf("Unsupported mxc_clock %d\n", clk); + break; + } + + return 0; +} + +u32 imx_get_fecclk(void) +{ + return mxc_get_clock(MXC_FEC_CLK); +} + +int enable_i2c_clk(u8 enable, u32 i2c_num) +{ + sc_ipc_t ipc; + sc_err_t err; + + if (i2c_num >= ARRAY_SIZE(imx_i2c_desc)) + return -EINVAL; + + ipc = gd->arch.ipc_channel_handle; + + if (enable) + err = sc_pm_clock_enable(ipc, imx_i2c_desc[i2c_num].rsrc, 2, + true, false); + else + err = sc_pm_clock_enable(ipc, imx_i2c_desc[i2c_num].rsrc, 2, + false, false); + + if (err != SC_ERR_NONE) { + printf("i2c clock error %d\n", err); + return -EPERM; + } + + return 0; +} + +u32 imx_get_i2cclk(u32 i2c_num) +{ + sc_err_t err; + sc_ipc_t ipc; + u32 clock_rate; + + if (i2c_num >= ARRAY_SIZE(imx_i2c_desc)) + return 0; + + ipc = gd->arch.ipc_channel_handle; + err = sc_pm_get_clock_rate(ipc, imx_i2c_desc[i2c_num].rsrc, 2, + &clock_rate); + if (err != SC_ERR_NONE) + return 0; + + return clock_rate; +} + +void init_clk_fspi(int index) +{ + sc_err_t scierr; + sc_pm_clock_rate_t rate; + sc_ipc_t ipchndl = gd->arch.ipc_channel_handle; + + /* Set FSPI0 clock root to 29 MHz */ + rate = 29000000; + scierr = sc_pm_set_clock_rate(ipchndl, SC_R_FSPI_0, SC_PM_CLK_PER, + &rate); + if (scierr != SC_ERR_NONE) { + puts("FSPI0 setrate failed\n"); + return; + } + + /* Enable FSPI0 clock root */ + scierr = sc_pm_clock_enable(ipchndl, SC_R_FSPI_0, SC_PM_CLK_PER, true, + false); + if (scierr != SC_ERR_NONE) { + puts("FSPI0 enable clock failed\n"); + return; + } +} + +void init_clk_gpmi_nand(void) +{ + sc_err_t scierr = 0; + sc_pm_clock_rate_t rate; + sc_ipc_t ipchndl = gd->arch.ipc_channel_handle; + + /* Set NAND BCH clock root to 50 MHz */ + rate = 50000000; + scierr = sc_pm_set_clock_rate(ipchndl, SC_R_NAND, SC_PM_CLK_PER, &rate); + if (scierr != SC_ERR_NONE) { + puts("NAND BCH set rate failed\n"); + return; + } + + /* Enable NAND BCH clock root */ + scierr = sc_pm_clock_enable(ipchndl, SC_R_NAND, SC_PM_CLK_PER, true, + false); + if (scierr != SC_ERR_NONE) { + puts("NAND BCH enable clock failed\n"); + return; + } + + /* Set NAND GPMI clock root to 50 MHz */ + rate = 50000000; + scierr = sc_pm_set_clock_rate(ipchndl, SC_R_NAND, SC_PM_CLK_MST_BUS, + &rate); + if (scierr != SC_ERR_NONE) { + puts("NAND GPMI set rate failed\n"); + return; + } + + /* Enable NAND GPMI clock root */ + scierr = sc_pm_clock_enable(ipchndl, SC_R_NAND, SC_PM_CLK_MST_BUS, + true, false); + if (scierr != SC_ERR_NONE) { + puts("NAND GPMI enable clock failed\n"); + return; + } +} + +void enable_usboh3_clk(bool enable) +{ + /* Dummy function */ +} + +void init_clk_usb3(int index) +{ + sc_err_t err; + sc_ipc_t ipc; + + ipc = gd->arch.ipc_channel_handle; + + err = sc_pm_clock_enable(ipc, SC_R_USB_2, SC_PM_CLK_MISC, true, false); + if (err != SC_ERR_NONE) + printf("USB3 set clock failed!, line=%d (error = %d)\n", + __LINE__, err); + + err = sc_pm_clock_enable(ipc, SC_R_USB_2, SC_PM_CLK_MST_BUS, true, + false); + if (err != SC_ERR_NONE) + printf("USB3 set clock failed!, line=%d (error = %d)\n", + __LINE__, err); + + err = sc_pm_clock_enable(ipc, SC_R_USB_2, SC_PM_CLK_PER, true, false); + if (err != SC_ERR_NONE) + printf("USB3 set clock failed!, line=%d (error = %d)\n", + __LINE__, err); +} + +int cdns3_enable_clks(int index) +{ + init_clk_usb3(index); + + return 0; +} + +int cdns3_disable_clks(int index) +{ + sc_err_t err; + sc_ipc_t ipc; + + ipc = gd->arch.ipc_channel_handle; + + err = sc_pm_clock_enable(ipc, SC_R_USB_2, SC_PM_CLK_MISC, false, false); + if (err != SC_ERR_NONE) + printf("USB3 disable clock failed!, line=%d (error = %d)\n", + __LINE__, err); + + err = sc_pm_clock_enable(ipc, SC_R_USB_2, SC_PM_CLK_MST_BUS, false, + false); + if (err != SC_ERR_NONE) + printf("USB3 disable clock failed!, line=%d (error = %d)\n", + __LINE__, err); + + err = sc_pm_clock_enable(ipc, SC_R_USB_2, SC_PM_CLK_PER, false, false); + if (err != SC_ERR_NONE) + printf("USB3 disable clock failed!, line=%d (error = %d)\n", + __LINE__, err); + + return 0; +} + +void init_clk_usdhc(u32 index) +{ +#ifdef CONFIG_IMX8QXP + sc_rsrc_t usdhcs[] = {SC_R_SDHC_0, SC_R_SDHC_1}; + u32 instances = 2; +#endif + + sc_err_t err; + sc_ipc_t ipc; + sc_pm_clock_rate_t actual = 400000000; + + ipc = gd->arch.ipc_channel_handle; + + if (index >= instances) + return; + + /* + * IMX8QXP USDHC_CLK_ROOT default source from DPLL, but this DPLL + * do not stable, will cause usdhc data transfer crc error. So here + * is a workaround, let USDHC_CLK_ROOT source from AVPLL. Due to + * AVPLL is fixed to 1000MHz, so here config USDHC1_CLK_ROOT to 333MHz, + * USDHC2_CLK_ROOT to 200MHz, make eMMC HS400ES work at 166MHz, and SD + * SDR104 work at 200MHz. + */ +#ifdef CONFIG_IMX8QXP + err = sc_pm_set_clock_parent(ipc, usdhcs[index], 2, SC_PM_PARENT_PLL1); + if (err != SC_ERR_NONE) + printf("SDHC_%d set clock parent failed!(error = %d)\n", + index, err); + + if (index == 1) + actual = 200000000; +#endif + + err = sc_pm_set_clock_rate(ipc, usdhcs[index], 2, &actual); + if (err != SC_ERR_NONE) { + printf("SDHC_%d set clock failed! (error = %d)\n", index, err); + return; + } + + if (actual != 400000000) + printf("Actual rate for SDHC_%d is %d\n", index, actual); + + err = sc_pm_clock_enable(ipc, usdhcs[index], SC_PM_CLK_PER, true, + false); + if (err != SC_ERR_NONE) { + printf("SDHC_%d per clk enable failed!\n", index); + return; + } +} + +void init_clk_fec(int index) +{ + sc_err_t err; + sc_ipc_t ipc; + sc_pm_clock_rate_t rate = 24000000; + sc_rsrc_t enet[2] = {SC_R_ENET_0, SC_R_ENET_1}; + + if (index > 1) + return; + + if (index == -1) + index = 0; + + ipc = gd->arch.ipc_channel_handle; + + /* Disable SC_R_ENET_0 clock root */ + err = sc_pm_clock_enable(ipc, enet[index], 0, false, false); + err |= sc_pm_clock_enable(ipc, enet[index], 2, false, false); + err |= sc_pm_clock_enable(ipc, enet[index], 4, false, false); + if (err != SC_ERR_NONE) { + printf("SC_R_ENET_0 disable clock failed! (error = %d)\n", err); + return; + } + + /* Set SC_R_ENET_0 clock root to 125 MHz */ + rate = 125000000; + + /* div = 8 clk_source = PLL_1 ss_slice #7 in verfication codes */ + err = sc_pm_set_clock_rate(ipc, enet[index], 2, &rate); + if (err != SC_ERR_NONE) { + printf("SC_R_ENET_0 set ref clock failed! (err = %d)\n", err); + return; + } + + /* Enable SC_R_ENET_0 clock root */ + err = sc_pm_clock_enable(ipc, enet[index], 0, true, true); + err |= sc_pm_clock_enable(ipc, enet[index], 2, true, true); + err |= sc_pm_clock_enable(ipc, enet[index], 4, true, true); + if (err != SC_ERR_NONE) { + printf("SC_R_ENET_0 enable clock failed! (error = %d)\n", err); + return; + } +}