From patchwork Sun Mar 15 13:43:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439049 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E6FC31668 for ; Sun, 15 Mar 2020 13:50:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D1ACB206B1 for ; Sun, 15 Mar 2020 13:50:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727766AbgCONuq (ORCPT ); Sun, 15 Mar 2020 09:50:46 -0400 Received: from inva020.nxp.com ([92.121.34.13]:55284 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727149AbgCONuq (ORCPT ); Sun, 15 Mar 2020 09:50:46 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 885A01A04EA; Sun, 15 Mar 2020 14:50:43 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 159D41A04E7; Sun, 15 Mar 2020 14:50:38 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 85A09402E4; Sun, 15 Mar 2020 21:50:31 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng , devicetree@vger.kernel.org Subject: [PATCH V6 01/12] dt-bindings: firmware: imx-scu: new binding to parse clocks from device tree Date: Sun, 15 Mar 2020 21:43:45 +0800 Message-Id: <1584279836-29825-2-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org There's a few limitations on the original one cell clock binding (#clock-cells = <1>) that we have to define some SW clock IDs for device tree to reference. This may cause troubles if we want to use common clock IDs for multi platforms support when the clock of those platforms are mostly the same. e.g. Current clock IDs name are defined with SS prefix. However the device may reside in different SS across CPUs, that means the SS prefix may not valid anymore for a new SoC. Furthermore, the device availability of those clocks may also vary a bit. For such situation, we want to eliminate the using of SW Clock IDs and change to use a more close to HW one instead. For SCU clocks usage, only two params required: Resource id + Clock Type. Both parameters are platform independent. So we could use two cells binding to pass those parameters, Cc: Sascha Hauer Cc: Michael Turquette Cc: devicetree@vger.kernel.org Acked-by: Shawn Guo Reviewed-by: Rob Herring Reviewed-by: Stephen Boyd Signed-off-by: Dong Aisheng --- ChangeLog: v4->v5: * no changes v3->v4: * add some comments for various clock types v2->v3: * Changed to two cells binding and register all clocks in driver instead of parse from device tree. v1->v2: * changed to one cell binding inspired by arm,scpi.txt Documentation/devicetree/bindings/arm/arm,scpi.txt Resource ID is encoded in 'reg' property. Clock type is encoded in generic clock-indices property. Then we don't have to search all the DT nodes to fetch those two value to construct clocks which is relatively low efficiency. * Add required power-domain property as well. --- .../bindings/arm/freescale/fsl,scu.txt | 12 ++++++---- include/dt-bindings/firmware/imx/rsrc.h | 23 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt index e07735a8c2c7..ee061befbb8e 100644 --- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt @@ -89,7 +89,10 @@ Required properties: "fsl,imx8qm-clock" "fsl,imx8qxp-clock" followed by "fsl,scu-clk" -- #clock-cells: Should be 1. Contains the Clock ID value. +- #clock-cells: Should be either + 2: Contains the Resource and Clock ID value. + or + 1: Contains the Clock ID value. (DEPRECATED) - clocks: List of clock specifiers, must contain an entry for each required entry in clock-names - clock-names: Should include entries "xtal_32KHz", "xtal_24MHz" @@ -195,7 +198,7 @@ firmware { clk: clk { compatible = "fsl,imx8qxp-clk", "fsl,scu-clk"; - #clock-cells = <1>; + #clock-cells = <2>; }; iomuxc { @@ -245,8 +248,7 @@ serial@5a060000 { ... pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lpuart0>; - clocks = <&clk IMX8QXP_UART0_CLK>, - <&clk IMX8QXP_UART0_IPG_CLK>; - clock-names = "per", "ipg"; + clocks = <&uart0_clk IMX_SC_R_UART_0 IMX_SC_PM_CLK_PER>; + clock-names = "ipg"; power-domains = <&pd IMX_SC_R_UART_0>; }; diff --git a/include/dt-bindings/firmware/imx/rsrc.h b/include/dt-bindings/firmware/imx/rsrc.h index 4e61f6485097..24c153dfaa72 100644 --- a/include/dt-bindings/firmware/imx/rsrc.h +++ b/include/dt-bindings/firmware/imx/rsrc.h @@ -547,4 +547,27 @@ #define IMX_SC_R_ATTESTATION 545 #define IMX_SC_R_LAST 546 +/* + * Defines for SC PM CLK + */ + +/* Normal device resource clock */ +#define IMX_SC_PM_CLK_SLV_BUS 0 /* Slave bus clock */ +#define IMX_SC_PM_CLK_MST_BUS 1 /* Master bus clock */ +#define IMX_SC_PM_CLK_PER 2 /* Peripheral clock */ +#define IMX_SC_PM_CLK_PHY 3 /* Phy clock */ +#define IMX_SC_PM_CLK_MISC 4 /* Misc clock */ + +/* Special clock types which do not belong to above normal clock types */ +#define IMX_SC_PM_CLK_MISC0 0 /* Misc 0 clock */ +#define IMX_SC_PM_CLK_MISC1 1 /* Misc 1 clock */ +#define IMX_SC_PM_CLK_MISC2 2 /* Misc 2 clock */ +#define IMX_SC_PM_CLK_MISC3 3 /* Misc 3 clock */ +#define IMX_SC_PM_CLK_MISC4 4 /* Misc 4 clock */ + +/* Special clock types for CPU/PLL/BYPASS only */ +#define IMX_SC_PM_CLK_CPU 2 /* CPU clock */ +#define IMX_SC_PM_CLK_PLL 4 /* PLL */ +#define IMX_SC_PM_CLK_BYPASS 4 /* Bypass clock */ + #endif /* __DT_BINDINGS_RSCRC_IMX_H */ From patchwork Sun Mar 15 13:43:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439047 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C80EB6CA for ; Sun, 15 Mar 2020 13:50:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B18AC20663 for ; Sun, 15 Mar 2020 13:50:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727705AbgCONuq (ORCPT ); Sun, 15 Mar 2020 09:50:46 -0400 Received: from inva021.nxp.com ([92.121.34.21]:57420 "EHLO inva021.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727163AbgCONuq (ORCPT ); Sun, 15 Mar 2020 09:50:46 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 83BC8200257; Sun, 15 Mar 2020 14:50:44 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id F23B020059A; Sun, 15 Mar 2020 14:50:38 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 6EF3E402F3; Sun, 15 Mar 2020 21:50:32 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng , devicetree@vger.kernel.org Subject: [PATCH V6 02/12] dt-bindings: clock: imx-lpcg: add support to parse clocks from device tree Date: Sun, 15 Mar 2020 21:43:46 +0800 Message-Id: <1584279836-29825-3-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org MX8QM and MX8QXP LPCG Clocks are mostly the same except they may reside in different subsystems across CPUs and also vary a bit on the availability. Same as SCU clock, we want to move the clock definition into device tree which can fully decouple the dependency of Clock ID definition from device tree and make us be able to write a fully generic lpcg clock driver. And we can also use the existence of clock nodes in device tree to address the device and clock availability differences across different SoCs. Cc: Sascha Hauer Cc: Michael Turquette Cc: devicetree@vger.kernel.org Acked-by: Shawn Guo Reviewed-by: Rob Herring Reviewed-by: Stephen Boyd Signed-off-by: Dong Aisheng --- ChangeLog: v4->v5: * no changes v3->v4: * change bit-offset property to clock-indices * use constant macro to define clock indinces * drop hw-autogate property which is still not used by drivers v2->v3: * no changes v1->v2: * Update example * Add power domain property --- .../bindings/clock/imx8qxp-lpcg.txt | 36 +++++++++++++++---- include/dt-bindings/clock/imx8-lpcg.h | 14 ++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 include/dt-bindings/clock/imx8-lpcg.h diff --git a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt index 965cfa42e025..cad8fc4284aa 100644 --- a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt +++ b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt @@ -11,6 +11,21 @@ enabled by these control bits, it might still not be running based on the base resource. Required properties: +- compatible: Should be one of: + "fsl,imx8qxp-lpcg" + "fsl,imx8qm-lpcg" followed by "fsl,imx8qxp-lpcg". +- reg: Address and length of the register set. +- #clock-cells: Should be 1. One LPCG supports multiple clocks. +- clocks: Input parent clocks phandle array for each clock. +- clock-indices: An integer array indicating the bit offset for each clock. + Refer to for the + supported LPCG clock indices. +- clock-output-names: Shall be the corresponding names of the outputs. + NOTE this property must be specified in the same order + as the clock-indices property. +- power-domains: Should contain the power domain used by this clock. + +Legacy binding (DEPRECATED): - compatible: Should be one of: "fsl,imx8qxp-lpcg-adma", "fsl,imx8qxp-lpcg-conn", @@ -33,10 +48,19 @@ Examples: #include -conn_lpcg: clock-controller@5b200000 { - compatible = "fsl,imx8qxp-lpcg-conn"; - reg = <0x5b200000 0xb0000>; +sdhc0_lpcg: clock-controller@5b200000 { + compatible = "fsl,imx8qxp-lpcg"; + reg = <0x5b200000 0x10000>; #clock-cells = <1>; + clocks = <&sdhc0_clk IMX_SC_PM_CLK_PER>, + <&conn_ipg_clk>, <&conn_axi_clk>; + clock-indices = , + , + ; + clock-output-names = "sdhc0_lpcg_per_clk", + "sdhc0_lpcg_ipg_clk", + "sdhc0_lpcg_ahb_clk"; + power-domains = <&pd IMX_SC_R_SDHC_0>; }; usdhc1: mmc@5b010000 { @@ -44,8 +68,8 @@ usdhc1: mmc@5b010000 { interrupt-parent = <&gic>; interrupts = ; reg = <0x5b010000 0x10000>; - clocks = <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK>, - <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_PER_CLK>, - <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_HCLK>; + clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>, + <&sdhc0_lpcg IMX_LPCG_CLK_0>, + <&sdhc0_lpcg IMX_LPCG_CLK_5>; clock-names = "ipg", "per", "ahb"; }; diff --git a/include/dt-bindings/clock/imx8-lpcg.h b/include/dt-bindings/clock/imx8-lpcg.h new file mode 100644 index 000000000000..df90aad26265 --- /dev/null +++ b/include/dt-bindings/clock/imx8-lpcg.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019 NXP + * Dong Aisheng + */ + +#define IMX_LPCG_CLK_0 0 +#define IMX_LPCG_CLK_1 4 +#define IMX_LPCG_CLK_2 8 +#define IMX_LPCG_CLK_3 12 +#define IMX_LPCG_CLK_4 16 +#define IMX_LPCG_CLK_5 20 +#define IMX_LPCG_CLK_6 24 +#define IMX_LPCG_CLK_7 28 From patchwork Sun Mar 15 13:43:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439053 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 976166CA for ; Sun, 15 Mar 2020 13:50:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 65D13206BE for ; Sun, 15 Mar 2020 13:50:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727767AbgCONus (ORCPT ); Sun, 15 Mar 2020 09:50:48 -0400 Received: from inva021.nxp.com ([92.121.34.21]:57448 "EHLO inva021.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727187AbgCONur (ORCPT ); Sun, 15 Mar 2020 09:50:47 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id B45282005A4; Sun, 15 Mar 2020 14:50:44 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 6F38E20059B; Sun, 15 Mar 2020 14:50:39 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 588204024E; Sun, 15 Mar 2020 21:50:33 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 03/12] clk: imx: scu: add two cells binding support Date: Sun, 15 Mar 2020 21:43:47 +0800 Message-Id: <1584279836-29825-4-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org This patch implements the new two cells binding for SCU clocks. The usage is as follows: clocks = <&uart0_clk IMX_SC_R_UART_0 IMX_SC_PM_CLK_PER> Due to each SCU clock is associated with a power domain, without power on the domain, the SCU clock can't work. So we create platform devices for each domain clock respectively and manually attach the required domain before register the clock devices, then we can register clocks in the clock platform driver accordingly. Note because we do not have power domain info in device tree and the SCU resource ID is the same for power domain and clock, so we use resource ID to find power domains. Later, we will also use this clock platform driver to support suspend/resume and runtime pm. Cc: Stephen Boyd Cc: Shawn Guo Cc: Sascha Hauer Cc: Michael Turquette Signed-off-by: Dong Aisheng --- ChangeLog: v4->v5: * remove global clock_cells * put node after using of_find_compatible_node() * using ERR_PTR(ret) instead of ERR_PTR(-ENOMEM) v4: no changes v3: new patch --- drivers/clk/imx/clk-imx8qxp.c | 129 ++++++++++++++++--------------- drivers/clk/imx/clk-scu.c | 140 +++++++++++++++++++++++++++++++++- drivers/clk/imx/clk-scu.h | 25 ++++-- 3 files changed, 227 insertions(+), 67 deletions(-) diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index 5e2903efc488..2ec3e0c4749d 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -22,9 +22,10 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) struct device_node *ccm_node = pdev->dev.of_node; struct clk_hw_onecell_data *clk_data; struct clk_hw **clks; + u32 clk_cells; int ret, i; - ret = imx_clk_scu_init(); + ret = imx_clk_scu_init(ccm_node); if (ret) return ret; @@ -33,6 +34,9 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) if (!clk_data) return -ENOMEM; + if (of_property_read_u32(ccm_node, "#clock-cells", &clk_cells)) + return -EINVAL; + clk_data->num = IMX_SCU_CLK_END; clks = clk_data->hws; @@ -55,78 +59,78 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) clks[IMX_LSIO_BUS_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 100000000); /* ARM core */ - clks[IMX_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU); + clks[IMX_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU, clk_cells); /* LSIO SS */ - clks[IMX_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER); - clks[IMX_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER); + clks[IMX_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER, clk_cells); /* ADMA SS */ - clks[IMX_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER); - clks[IMX_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER); + clks[IMX_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER, clk_cells); /* Connectivity */ - clks[IMX_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER); - clks[IMX_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER); - clks[IMX_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER); - clks[IMX_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER); - clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS); - clks[IMX_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0); - clks[IMX_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER); - clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS); - clks[IMX_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0); - clks[IMX_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS); - clks[IMX_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER); - clks[IMX_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER); - clks[IMX_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS); - clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC); + clks[IMX_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS, clk_cells); + clks[IMX_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0, clk_cells); + clks[IMX_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS, clk_cells); + clks[IMX_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0, clk_cells); + clks[IMX_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS, clk_cells); + clks[IMX_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS, clk_cells); + clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC, clk_cells); /* Display controller SS */ - clks[IMX_DC0_DISP0_CLK] = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0); - clks[IMX_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1); + clks[IMX_DC0_DISP0_CLK] = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0, clk_cells); + clks[IMX_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1, clk_cells); /* MIPI-LVDS SS */ - clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2); - clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2); + clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells); + clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells); /* MIPI CSI SS */ - clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER); - clks[IMX_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC); - clks[IMX_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER); - clks[IMX_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER); + clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC, clk_cells); + clks[IMX_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); /* GPU SS */ - clks[IMX_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER); - clks[IMX_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC); + clks[IMX_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC, clk_cells); for (i = 0; i < clk_data->num; i++) { if (IS_ERR(clks[i])) @@ -134,7 +138,12 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) i, PTR_ERR(clks[i])); } - return of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data); + if (clk_cells == 2) + ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks); + else + ret = of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data); + + return ret; } static const struct of_device_id imx8qxp_match[] = { diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index b8b2072742a5..4fadff14d8b2 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include #include "clk-scu.h" @@ -16,6 +19,20 @@ #define IMX_SIP_SET_CPUFREQ 0x00 static struct imx_sc_ipc *ccm_ipc_handle; +struct device_node *pd_np; + +struct imx_scu_clk_node { + const char *name; + u32 rsrc; + u8 clk_type; + const char * const *parents; + int num_parents; + + struct clk_hw *hw; + struct list_head node; +}; + +struct list_head imx_scu_clks[IMX_SC_R_LAST]; /* * struct clk_scu - Description of one SCU clock @@ -128,9 +145,32 @@ static inline struct clk_scu *to_clk_scu(struct clk_hw *hw) return container_of(hw, struct clk_scu, hw); } -int imx_clk_scu_init(void) +int imx_clk_scu_init(struct device_node *np) { - return imx_scu_get_handle(&ccm_ipc_handle); + struct platform_device *pd_dev; + u32 clk_cells; + int ret, i; + + ret = imx_scu_get_handle(&ccm_ipc_handle); + if (ret) + return ret; + + if (of_property_read_u32(np, "#clock-cells", &clk_cells)) + return -EINVAL; + + if (clk_cells == 2) { + for (i = 0; i < IMX_SC_R_LAST; i++) + INIT_LIST_HEAD(&imx_scu_clks[i]); + + pd_np = of_find_compatible_node(NULL, NULL, "fsl,scu-pd"); + pd_dev = of_find_device_by_node(pd_np); + if (!pd_dev || !device_is_bound(&pd_dev->dev)) { + of_node_put(pd_np); + return -EPROBE_DEFER; + } + } + + return 0; } /* @@ -387,3 +427,99 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents, return hw; } + +struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec, + void *data) +{ + unsigned int rsrc = clkspec->args[0]; + unsigned int idx = clkspec->args[1]; + struct list_head *scu_clks = data; + struct imx_scu_clk_node *clk; + + list_for_each_entry(clk, &scu_clks[rsrc], node) { + if (clk->clk_type == idx) + return clk->hw; + } + + return ERR_PTR(-ENODEV); +} + +static int imx_clk_scu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct imx_scu_clk_node *clk = dev_get_platdata(dev); + struct clk_hw *hw; + + hw = __imx_clk_scu(clk->name, clk->parents, clk->num_parents, + clk->rsrc, clk->clk_type); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + clk->hw = hw; + list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]); + + dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc, + clk->clk_type); + + return 0; +} + +static struct platform_driver imx_clk_scu_driver = { + .driver = { + .name = "imx-scu-clk", + .suppress_bind_attrs = true, + }, + .probe = imx_clk_scu_probe, +}; +builtin_platform_driver(imx_clk_scu_driver); + +static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id) +{ + struct of_phandle_args genpdspec = { + .np = pd_np, + .args_count = 1, + .args[0] = rsrc_id, + }; + + return of_genpd_add_device(&genpdspec, dev); +} + +struct clk_hw *imx_clk_scu_alloc_dev(const char *name, + const char * const *parents, + int num_parents, u32 rsrc_id, u8 clk_type) +{ + struct imx_scu_clk_node clk = { + .name = name, + .rsrc = rsrc_id, + .clk_type = clk_type, + .parents = parents, + .num_parents = num_parents, + }; + struct platform_device *pdev; + int ret; + + pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE); + if (!pdev) { + pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n", + name, rsrc_id, clk_type); + return ERR_PTR(-ENOMEM); + } + + ret = platform_device_add_data(pdev, &clk, sizeof(clk)); + if (ret) { + platform_device_put(pdev); + return ERR_PTR(ret); + } + + pdev->driver_override = "imx-scu-clk"; + + ret = imx_clk_scu_attach_pd(&pdev->dev, rsrc_id); + if (ret) + pr_warn("%s: failed to attached the power domain %d\n", + name, ret); + + platform_device_add(pdev); + + /* For API backwards compatiblilty, simply return NULL for success */ + return NULL; +} diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index 2bcfaf06a458..a512f81ed801 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -8,22 +8,37 @@ #define __IMX_CLK_SCU_H #include +#include -int imx_clk_scu_init(void); +extern struct list_head imx_scu_clks[]; + +int imx_clk_scu_init(struct device_node *np); +struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec, + void *data); +struct clk_hw *imx_clk_scu_alloc_dev(const char *name, + const char * const *parents, + int num_parents, u32 rsrc_id, u8 clk_type); struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents, int num_parents, u32 rsrc_id, u8 clk_type); static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, - u8 clk_type) + u8 clk_type, u8 clk_cells) { - return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type); + if (clk_cells == 2) + return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type); + else + return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type); } static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents, - int num_parents, u32 rsrc_id, u8 clk_type) + int num_parents, u32 rsrc_id, u8 clk_type, + u8 clk_cells) { - return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type); + if (clk_cells == 2) + return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type); + else + return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type); } struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, From patchwork Sun Mar 15 13:43:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439051 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 111FD1890 for ; Sun, 15 Mar 2020 13:50:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F105B206B1 for ; Sun, 15 Mar 2020 13:50:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727149AbgCONuq (ORCPT ); Sun, 15 Mar 2020 09:50:46 -0400 Received: from inva021.nxp.com ([92.121.34.21]:57466 "EHLO inva021.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727498AbgCONuq (ORCPT ); Sun, 15 Mar 2020 09:50:46 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 2AE7720059A; Sun, 15 Mar 2020 14:50:45 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 512CA20058A; Sun, 15 Mar 2020 14:50:40 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 41DEB402FC; Sun, 15 Mar 2020 21:50:34 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 04/12] clk: imx: scu: bypass cpu power domains Date: Sun, 15 Mar 2020 21:43:48 +0800 Message-Id: <1584279836-29825-5-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org Bypass cpu power domains which are owned by ATF. Signed-off-by: Dong Aisheng Reviewed-by: Stephen Boyd --- ChangeLog: v5: * remove unnecessary () v4: no changes v3: new patch --- drivers/clk/imx/clk-scu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 4fadff14d8b2..4c1980d5901d 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -481,6 +481,10 @@ static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id) .args[0] = rsrc_id, }; + if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53 || + rsrc_id == IMX_SC_R_A72) + return 0; + return of_genpd_add_device(&genpdspec, dev); } From patchwork Sun Mar 15 13:43:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439055 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 299111668 for ; Sun, 15 Mar 2020 13:50:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 13E8420674 for ; Sun, 15 Mar 2020 13:50:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727187AbgCONus (ORCPT ); Sun, 15 Mar 2020 09:50:48 -0400 Received: from inva021.nxp.com ([92.121.34.21]:57498 "EHLO inva021.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727498AbgCONus (ORCPT ); Sun, 15 Mar 2020 09:50:48 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 7275120058B; Sun, 15 Mar 2020 14:50:46 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 63E4020059D; Sun, 15 Mar 2020 14:50:41 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 25018402FF; Sun, 15 Mar 2020 21:50:35 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 05/12] clk: imx: scu: allow scu clk to take device pointer Date: Sun, 15 Mar 2020 21:43:49 +0800 Message-Id: <1584279836-29825-6-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org Used to support runtime pm. Cc: Stephen Boyd Cc: Shawn Guo Cc: Sascha Hauer Cc: Michael Turquette Signed-off-by: Dong Aisheng Reviewed-by: Stephen Boyd --- ChangeLog: v4->v5: * no changes v3->v4: * add the missing dev poninter when call __imx_clk_scu in probe v3: new patch --- drivers/clk/imx/clk-scu.c | 9 +++++---- drivers/clk/imx/clk-scu.h | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 4c1980d5901d..d474753712f7 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -384,8 +384,9 @@ static const struct clk_ops clk_scu_cpu_ops = { .unprepare = clk_scu_unprepare, }; -struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents, - int num_parents, u32 rsrc_id, u8 clk_type) +struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, + const char * const *parents, int num_parents, + u32 rsrc_id, u8 clk_type) { struct clk_init_data init; struct clk_scu *clk; @@ -419,7 +420,7 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents, clk->hw.init = &init; hw = &clk->hw; - ret = clk_hw_register(NULL, hw); + ret = clk_hw_register(dev, hw); if (ret) { kfree(clk); hw = ERR_PTR(ret); @@ -450,7 +451,7 @@ static int imx_clk_scu_probe(struct platform_device *pdev) struct imx_scu_clk_node *clk = dev_get_platdata(dev); struct clk_hw *hw; - hw = __imx_clk_scu(clk->name, clk->parents, clk->num_parents, + hw = __imx_clk_scu(NULL, clk->name, clk->parents, clk->num_parents, clk->rsrc, clk->clk_type); if (IS_ERR(hw)) return PTR_ERR(hw); diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index a512f81ed801..11eb3781ab6b 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -19,8 +19,9 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, const char * const *parents, int num_parents, u32 rsrc_id, u8 clk_type); -struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents, - int num_parents, u32 rsrc_id, u8 clk_type); +struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, + const char * const *parents, int num_parents, + u32 rsrc_id, u8 clk_type); static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type, u8 clk_cells) @@ -28,7 +29,7 @@ static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, if (clk_cells == 2) return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type); else - return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type); + return __imx_clk_scu(NULL, name, NULL, 0, rsrc_id, clk_type); } static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents, @@ -38,7 +39,7 @@ static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const * if (clk_cells == 2) return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type); else - return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type); + return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type); } struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, From patchwork Sun Mar 15 13:43:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439059 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DDD2D1668 for ; Sun, 15 Mar 2020 13:50:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BC897206B1 for ; Sun, 15 Mar 2020 13:50:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728061AbgCONuw (ORCPT ); Sun, 15 Mar 2020 09:50:52 -0400 Received: from inva021.nxp.com ([92.121.34.21]:57552 "EHLO inva021.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727778AbgCONuw (ORCPT ); Sun, 15 Mar 2020 09:50:52 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 3649E2005A7; Sun, 15 Mar 2020 14:50:50 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 6573620058A; Sun, 15 Mar 2020 14:50:45 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id F34CE40302; Sun, 15 Mar 2020 21:50:35 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 06/12] clk: imx: scu: add runtime pm support Date: Sun, 15 Mar 2020 21:43:50 +0800 Message-Id: <1584279836-29825-7-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org Add runtime pm support Cc: Stephen Boyd Cc: Shawn Guo Cc: Sascha Hauer Cc: Michael Turquette Signed-off-by: Dong Aisheng Reviewed-by: Stephen Boyd --- ChangeLog: v4->v5: no changes v3: new patch --- drivers/clk/imx/clk-scu.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index d474753712f7..7c7a839a3569 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "clk-scu.h" @@ -450,15 +451,32 @@ static int imx_clk_scu_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct imx_scu_clk_node *clk = dev_get_platdata(dev); struct clk_hw *hw; + int ret; + + pm_runtime_set_suspended(dev); + pm_runtime_set_autosuspend_delay(dev, 50); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(dev); + + ret = pm_runtime_get_sync(dev); + if (ret) { + pm_runtime_disable(dev); + return ret; + } - hw = __imx_clk_scu(NULL, clk->name, clk->parents, clk->num_parents, + hw = __imx_clk_scu(dev, clk->name, clk->parents, clk->num_parents, clk->rsrc, clk->clk_type); - if (IS_ERR(hw)) + if (IS_ERR(hw)) { + pm_runtime_disable(dev); return PTR_ERR(hw); + } clk->hw = hw; list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc, clk->clk_type); From patchwork Sun Mar 15 13:43:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439057 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4F5891667 for ; Sun, 15 Mar 2020 13:50:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 39E90206BE for ; Sun, 15 Mar 2020 13:50:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728055AbgCONuw (ORCPT ); Sun, 15 Mar 2020 09:50:52 -0400 Received: from inva020.nxp.com ([92.121.34.13]:55338 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727498AbgCONuv (ORCPT ); Sun, 15 Mar 2020 09:50:51 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id F05D31A04DF; Sun, 15 Mar 2020 14:50:49 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 2D8F31A04E7; Sun, 15 Mar 2020 14:50:45 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id CD4854030B; Sun, 15 Mar 2020 21:50:36 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 07/12] clk: imx: scu: add suspend/resume support Date: Sun, 15 Mar 2020 21:43:51 +0800 Message-Id: <1584279836-29825-8-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org Clock state will be lost when its power domain is completely off during system suspend/resume. So we save and restore the state accordingly in suspend/resume callback. Cc: Stephen Boyd Cc: Shawn Guo Cc: Sascha Hauer Cc: Michael Turquette Signed-off-by: Dong Aisheng Reviewed-by: Stephen Boyd --- ChangeLog: v5: * make suspend/resume function static v4: no changes v3: new patch --- drivers/clk/imx/clk-scu.c | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 7c7a839a3569..7b910922aecf 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -45,6 +45,10 @@ struct clk_scu { struct clk_hw hw; u16 rsrc_id; u8 clk_type; + + /* for state save&restore */ + bool is_enabled; + u32 rate; }; /* @@ -427,6 +431,9 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, hw = ERR_PTR(ret); } + if (dev) + dev_set_drvdata(dev, clk); + return hw; } @@ -483,10 +490,52 @@ static int imx_clk_scu_probe(struct platform_device *pdev) return 0; } +static int __maybe_unused imx_clk_scu_suspend(struct device *dev) +{ + struct clk_scu *clk = dev_get_drvdata(dev); + + clk->rate = clk_hw_get_rate(&clk->hw); + clk->is_enabled = clk_hw_is_enabled(&clk->hw); + + if (clk->rate) + dev_dbg(dev, "save rate %d\n", clk->rate); + + if (clk->is_enabled) + dev_dbg(dev, "save enabled state\n"); + + return 0; +} + +static int __maybe_unused imx_clk_scu_resume(struct device *dev) +{ + struct clk_scu *clk = dev_get_drvdata(dev); + int ret = 0; + + if (clk->rate) { + ret = clk_scu_set_rate(&clk->hw, clk->rate, 0); + dev_dbg(dev, "restore rate %d %s\n", clk->rate, + !ret ? "success" : "failed"); + } + + if (clk->is_enabled) { + ret = clk_scu_prepare(&clk->hw); + dev_dbg(dev, "restore enabled state %s\n", + !ret ? "success" : "failed"); + } + + return ret; +} + +static const struct dev_pm_ops imx_clk_scu_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_scu_suspend, + imx_clk_scu_resume) +}; + static struct platform_driver imx_clk_scu_driver = { .driver = { .name = "imx-scu-clk", .suppress_bind_attrs = true, + .pm = &imx_clk_scu_pm_ops, }, .probe = imx_clk_scu_probe, }; From patchwork Sun Mar 15 13:43:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439061 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D57AC6CA for ; Sun, 15 Mar 2020 13:50:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B6A15206E9 for ; Sun, 15 Mar 2020 13:50:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728068AbgCONux (ORCPT ); Sun, 15 Mar 2020 09:50:53 -0400 Received: from inva020.nxp.com ([92.121.34.13]:55366 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727779AbgCONux (ORCPT ); Sun, 15 Mar 2020 09:50:53 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 969141A04EA; Sun, 15 Mar 2020 14:50:50 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 8E0211A04CE; Sun, 15 Mar 2020 14:50:45 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id A7AE14030D; Sun, 15 Mar 2020 21:50:37 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 08/12] clk: imx: imx8qxp-lpcg: add parsing clocks from device tree Date: Sun, 15 Mar 2020 21:43:52 +0800 Message-Id: <1584279836-29825-9-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org One LPCG controller supports up to 8 clock outputs while each of them is fixed to 4 bits. It supports only gating function with fixed bits. So we can use the clk-indices to fetch the corresponding clock idx from device tree. With this way, we can write a generic LPCG clock drivers. This patch add that support to parse clocks from device tree. Cc: Stephen Boyd Cc: Shawn Guo Cc: Sascha Hauer Cc: Michael Turquette Signed-off-by: Dong Aisheng Reviewed-by: Stephen Boyd --- Changelog: v4->v5: * add error check for devm_of_clk_add_hw_provider * add more commit message * a few minor updates v3->v4: * remove hw_autogate which is not still used by driver * use clock-indices to indicate LPCG clock bit offset v1->v3: no changes --- drivers/clk/imx/clk-imx8qxp-lpcg.c | 124 +++++++++++++++++++++++++++++ drivers/clk/imx/clk-lpcg-scu.c | 8 ++ drivers/clk/imx/clk-scu.h | 1 + 3 files changed, 133 insertions(+) diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c index 04c8ee35e14c..1881d7f3ccec 100644 --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -157,6 +158,122 @@ static const struct imx8qxp_ss_lpcg imx8qxp_ss_lsio = { .num_max = IMX_LSIO_LPCG_CLK_END, }; +#define IMX_LPCG_MAX_CLKS 8 + +static struct clk_hw *imx_lpcg_of_clk_src_get(struct of_phandle_args *clkspec, + void *data) +{ + struct clk_hw_onecell_data *hw_data = data; + unsigned int idx = clkspec->args[0] / 4; + + if (idx >= hw_data->num) { + pr_err("%s: invalid index %u\n", __func__, idx); + return ERR_PTR(-EINVAL); + } + + return hw_data->hws[idx]; +} + +static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev, + struct device_node *np) +{ + const char *output_names[IMX_LPCG_MAX_CLKS]; + const char *parent_names[IMX_LPCG_MAX_CLKS]; + unsigned int bit_offset[IMX_LPCG_MAX_CLKS]; + struct clk_hw_onecell_data *clk_data; + struct clk_hw **clk_hws; + struct resource *res; + void __iomem *base; + int count; + int idx; + int ret; + int i; + + if (!of_device_is_compatible(np, "fsl,imx8qxp-lpcg")) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + count = of_property_count_u32_elems(np, "clock-indices"); + if (count < 0) { + dev_err(&pdev->dev, "failed to count clocks\n"); + return -EINVAL; + } + + /* + * A trick here is that we set the num of clks to the MAX instead + * of the count from clock-indices because one LPCG supports up to + * 8 clock outputs which each of them is fixed to 4 bits. Then we can + * easily get the clock by clk-indices (bit-offset) / 4. + * And the cost is very limited few pointers. + */ + + clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws, + IMX_LPCG_MAX_CLKS), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->num = IMX_LPCG_MAX_CLKS; + clk_hws = clk_data->hws; + + ret = of_property_read_u32_array(np, "clock-indices", bit_offset, + count); + if (ret < 0) { + dev_err(&pdev->dev, "failed to read clock-indices\n"); + return -EINVAL; + } + + ret = of_clk_parent_fill(np, parent_names, count); + if (ret != count) { + dev_err(&pdev->dev, "failed to get clock parent names\n"); + return count; + } + + ret = of_property_read_string_array(np, "clock-output-names", + output_names, count); + if (ret != count) { + dev_err(&pdev->dev, "failed to read clock-output-names\n"); + return -EINVAL; + } + + for (i = 0; i < count; i++) { + idx = bit_offset[i] / 4; + if (idx > IMX_LPCG_MAX_CLKS) { + dev_warn(&pdev->dev, "invalid bit offset of clock %d\n", + i); + ret = -EINVAL; + goto unreg; + } + + clk_hws[idx] = imx_clk_lpcg_scu(output_names[i], + parent_names[i], 0, base, + bit_offset[i], false); + if (IS_ERR(clk_hws[idx])) { + dev_warn(&pdev->dev, "failed to register clock %d\n", + idx); + ret = PTR_ERR(clk_hws[idx]); + goto unreg; + } + } + + ret = devm_of_clk_add_hw_provider(&pdev->dev, imx_lpcg_of_clk_src_get, + clk_data); + if (!ret) + return 0; + +unreg: + while (--i >= 0) { + idx = bit_offset[i] / 4; + if (clk_hws[idx]) + imx_clk_lpcg_scu_unregister(clk_hws[idx]); + } + + return ret; +} + static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -167,8 +284,14 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) struct resource *res; struct clk_hw **clks; void __iomem *base; + int ret; int i; + /* try new binding to parse clocks from device tree first */ + ret = imx_lpcg_parse_clks_from_dt(pdev, np); + if (!ret) + return 0; + ss_lpcg = of_device_get_match_data(dev); if (!ss_lpcg) return -ENODEV; @@ -219,6 +342,7 @@ static const struct of_device_id imx8qxp_lpcg_match[] = { { .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, }, { .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, }, { .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, }, + { .compatible = "fsl,imx8qxp-lpcg", NULL }, { /* sentinel */ } }; diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c index a73a799fb777..897a4c3c02e2 100644 --- a/drivers/clk/imx/clk-lpcg-scu.c +++ b/drivers/clk/imx/clk-lpcg-scu.c @@ -114,3 +114,11 @@ struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, return hw; } + +void imx_clk_lpcg_scu_unregister(struct clk_hw *hw) +{ + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw); + + clk_hw_unregister(&clk->hw); + kfree(clk); +} diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index 11eb3781ab6b..2db226a2401f 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -45,4 +45,5 @@ static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const * struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, bool hw_gate); +void imx_clk_lpcg_scu_unregister(struct clk_hw *hw); #endif From patchwork Sun Mar 15 13:43:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439067 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 54BB21667 for ; Sun, 15 Mar 2020 13:50:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3EA3820674 for ; Sun, 15 Mar 2020 13:50:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727498AbgCONuy (ORCPT ); Sun, 15 Mar 2020 09:50:54 -0400 Received: from inva020.nxp.com ([92.121.34.13]:55404 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727804AbgCONux (ORCPT ); Sun, 15 Mar 2020 09:50:53 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 441591A04F7; Sun, 15 Mar 2020 14:50:51 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 76A141A0509; Sun, 15 Mar 2020 14:50:46 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 80E0C4031E; Sun, 15 Mar 2020 21:50:38 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 09/12] clk: imx: lpcg: allow lpcg clk to take device pointer Date: Sun, 15 Mar 2020 21:43:53 +0800 Message-Id: <1584279836-29825-10-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org Used to support runtime pm. Signed-off-by: Dong Aisheng Reviewed-by: Stephen Boyd --- ChangeLog: v4->v5: no changes v3: new patch --- drivers/clk/imx/clk-lpcg-scu.c | 8 ++++---- drivers/clk/imx/clk-scu.h | 24 ++++++++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c index 897a4c3c02e2..2242e5047a0e 100644 --- a/drivers/clk/imx/clk-lpcg-scu.c +++ b/drivers/clk/imx/clk-lpcg-scu.c @@ -80,9 +80,9 @@ static const struct clk_ops clk_lpcg_scu_ops = { .disable = clk_lpcg_scu_disable, }; -struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, - unsigned long flags, void __iomem *reg, - u8 bit_idx, bool hw_gate) +struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, bool hw_gate) { struct clk_lpcg_scu *clk; struct clk_init_data init; @@ -106,7 +106,7 @@ struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, clk->hw.init = &init; hw = &clk->hw; - ret = clk_hw_register(NULL, hw); + ret = clk_hw_register(dev, hw); if (ret) { kfree(clk); hw = ERR_PTR(ret); diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index 2db226a2401f..6b29713a71d2 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -23,6 +23,11 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, const char * const *parents, int num_parents, u32 rsrc_id, u8 clk_type); +struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, bool hw_gate); +void imx_clk_lpcg_scu_unregister(struct clk_hw *hw); + static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type, u8 clk_cells) { @@ -42,8 +47,19 @@ static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const * return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type); } -struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, - unsigned long flags, void __iomem *reg, - u8 bit_idx, bool hw_gate); -void imx_clk_lpcg_scu_unregister(struct clk_hw *hw); +static inline struct clk_hw *imx_clk_lpcg_scu_dev(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, bool hw_gate) +{ + return __imx_clk_lpcg_scu(dev, name, parent_name, flags, reg, + bit_idx, hw_gate); +} + +static inline struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name, + unsigned long flags, void __iomem *reg, + u8 bit_idx, bool hw_gate) +{ + return __imx_clk_lpcg_scu(NULL, name, parent_name, flags, reg, + bit_idx, hw_gate); +} #endif From patchwork Sun Mar 15 13:43:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439069 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 745521894 for ; Sun, 15 Mar 2020 13:50:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5F4E5206E9 for ; Sun, 15 Mar 2020 13:50:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727804AbgCONuy (ORCPT ); Sun, 15 Mar 2020 09:50:54 -0400 Received: from inva020.nxp.com ([92.121.34.13]:55426 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728059AbgCONux (ORCPT ); Sun, 15 Mar 2020 09:50:53 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id E9B0C1A0518; Sun, 15 Mar 2020 14:50:51 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 2814F1A050F; Sun, 15 Mar 2020 14:50:47 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 59FA140326; Sun, 15 Mar 2020 21:50:39 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 10/12] clk: imx: clk-imx8qxp-lpcg: add runtime pm support Date: Sun, 15 Mar 2020 21:43:54 +0800 Message-Id: <1584279836-29825-11-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org add runtime pm support Signed-off-by: Dong Aisheng Reviewed-by: Stephen Boyd --- ChangeLog: v4->v5: * minor err check fix v3->v4: * disable rpm when error out v3: new patch --- drivers/clk/imx/clk-imx8qxp-lpcg.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c index 1881d7f3ccec..3385de76f6c7 100644 --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "clk-scu.h" @@ -239,6 +240,12 @@ static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev, return -EINVAL; } + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, 500); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + for (i = 0; i < count; i++) { idx = bit_offset[i] / 4; if (idx > IMX_LPCG_MAX_CLKS) { @@ -248,9 +255,9 @@ static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev, goto unreg; } - clk_hws[idx] = imx_clk_lpcg_scu(output_names[i], - parent_names[i], 0, base, - bit_offset[i], false); + clk_hws[idx] = imx_clk_lpcg_scu_dev(&pdev->dev, output_names[i], + parent_names[i], 0, base, + bit_offset[i], false); if (IS_ERR(clk_hws[idx])) { dev_warn(&pdev->dev, "failed to register clock %d\n", idx); @@ -261,8 +268,13 @@ static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev, ret = devm_of_clk_add_hw_provider(&pdev->dev, imx_lpcg_of_clk_src_get, clk_data); - if (!ret) - return 0; + if (ret) + goto unreg; + + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + + return 0; unreg: while (--i >= 0) { @@ -271,6 +283,8 @@ static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev, imx_clk_lpcg_scu_unregister(clk_hws[idx]); } + pm_runtime_disable(&pdev->dev); + return ret; } From patchwork Sun Mar 15 13:43:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439063 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0096C1668 for ; Sun, 15 Mar 2020 13:50:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DF3F920663 for ; Sun, 15 Mar 2020 13:50:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727779AbgCONux (ORCPT ); Sun, 15 Mar 2020 09:50:53 -0400 Received: from inva021.nxp.com ([92.121.34.21]:57578 "EHLO inva021.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727498AbgCONux (ORCPT ); Sun, 15 Mar 2020 09:50:53 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id B3D20200257; Sun, 15 Mar 2020 14:50:51 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id E50B120059B; Sun, 15 Mar 2020 14:50:46 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 33471402AE; Sun, 15 Mar 2020 21:50:40 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 11/12] clk: imx: lpcg: add suspend/resume support Date: Sun, 15 Mar 2020 21:43:55 +0800 Message-Id: <1584279836-29825-12-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org LPCG clock state may be lost when it's power domain is completely off during system suspend/resume and we need save and restore the state properly. Signed-off-by: Dong Aisheng Reviewed-by: Stephen Boyd --- ChangeLog: v5: * make suspend/resume function static * improve code comments v4: no changes v3: new patch --- drivers/clk/imx/clk-imx8qxp-lpcg.c | 1 + drivers/clk/imx/clk-lpcg-scu.c | 37 ++++++++++++++++++++++++++++++ drivers/clk/imx/clk-scu.h | 1 + 3 files changed, 39 insertions(+) diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c index 3385de76f6c7..4d4a3a65bcec 100644 --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c @@ -364,6 +364,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = { .driver = { .name = "imx8qxp-lpcg-clk", .of_match_table = imx8qxp_lpcg_match, + .pm = &imx_clk_lpcg_scu_pm_ops, .suppress_bind_attrs = true, }, .probe = imx8qxp_lpcg_clk_probe, diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c index 2242e5047a0e..5bd8af371059 100644 --- a/drivers/clk/imx/clk-lpcg-scu.c +++ b/drivers/clk/imx/clk-lpcg-scu.c @@ -33,6 +33,9 @@ struct clk_lpcg_scu { void __iomem *reg; u8 bit_idx; bool hw_gate; + + /* for state save&restore */ + u32 state; }; #define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw) @@ -112,6 +115,9 @@ struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, hw = ERR_PTR(ret); } + if (dev) + dev_set_drvdata(dev, clk); + return hw; } @@ -122,3 +128,34 @@ void imx_clk_lpcg_scu_unregister(struct clk_hw *hw) clk_hw_unregister(&clk->hw); kfree(clk); } + +static int __maybe_unused imx_clk_lpcg_scu_suspend(struct device *dev) +{ + struct clk_lpcg_scu *clk = dev_get_drvdata(dev); + + clk->state = readl_relaxed(clk->reg); + dev_dbg(dev, "save lpcg state 0x%x\n", clk->state); + + return 0; +} + +static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev) +{ + struct clk_lpcg_scu *clk = dev_get_drvdata(dev); + + /* + * FIXME: Sometimes writes don't work unless the CPU issues + * them twice + */ + + writel(clk->state, clk->reg); + writel(clk->state, clk->reg); + dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state); + + return 0; +} + +const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_lpcg_scu_suspend, + imx_clk_lpcg_scu_resume) +}; diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index 6b29713a71d2..b1dfdaf0734e 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -11,6 +11,7 @@ #include extern struct list_head imx_scu_clks[]; +extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops; int imx_clk_scu_init(struct device_node *np); struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec, From patchwork Sun Mar 15 13:43:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 11439071 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C7B7F6CA for ; Sun, 15 Mar 2020 13:50:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AE7B0206B1 for ; Sun, 15 Mar 2020 13:50:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728059AbgCONuy (ORCPT ); Sun, 15 Mar 2020 09:50:54 -0400 Received: from inva020.nxp.com ([92.121.34.13]:55444 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727778AbgCONuy (ORCPT ); Sun, 15 Mar 2020 09:50:54 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 64BE41A04CE; Sun, 15 Mar 2020 14:50:52 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 96ABD1A0528; Sun, 15 Mar 2020 14:50:47 +0100 (CET) Received: from localhost.localdomain (shlinux2.ap.freescale.net [10.192.224.44]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 0CB87402C1; Sun, 15 Mar 2020 21:50:40 +0800 (SGT) From: Dong Aisheng To: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, sboyd@kernel.org, mturquette@baylibre.com, shawnguo@kernel.org, fabio.estevam@nxp.com, linux-imx@nxp.com, kernel@pengutronix.de, Dong Aisheng Subject: [PATCH V6 12/12] clk: imx: scu: unregister clocks if add provider failed Date: Sun, 15 Mar 2020 21:43:56 +0800 Message-Id: <1584279836-29825-13-git-send-email-aisheng.dong@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> References: <1584279836-29825-1-git-send-email-aisheng.dong@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org Unregister clocks if add provider failed Signed-off-by: Dong Aisheng --- ChangeLog: v6: new patch --- drivers/clk/imx/clk-imx8qxp.c | 11 +++++++++-- drivers/clk/imx/clk-scu.c | 13 +++++++++++++ drivers/clk/imx/clk-scu.h | 2 ++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index 2ec3e0c4749d..e615214495c0 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -138,10 +138,17 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) i, PTR_ERR(clks[i])); } - if (clk_cells == 2) + if (clk_cells == 2) { ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks); - else + if (ret) + imx_clk_scu_unregister(); + } else { + /* + * NOTE: we did not unregister clocks for the legacy way cause + * it will be removed later. + */ ret = of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data); + } return ret; } diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 7b910922aecf..1933cf90ae30 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -595,3 +595,16 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, /* For API backwards compatiblilty, simply return NULL for success */ return NULL; } + +void imx_clk_scu_unregister(void) +{ + struct imx_scu_clk_node *clk; + int i; + + for (i = 0; i < IMX_SC_R_LAST; i++) { + list_for_each_entry(clk, &imx_scu_clks[i], node) { + clk_hw_unregister(clk->hw); + kfree(clk); + } + } +} diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index b1dfdaf0734e..e8352164923e 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -24,6 +24,8 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, const char * const *parents, int num_parents, u32 rsrc_id, u8 clk_type); +void imx_clk_scu_unregister(void); + struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, bool hw_gate);