From patchwork Wed Jul 24 12:38:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 11056787 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6060D746 for ; Wed, 24 Jul 2019 12:39:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4FA5A28803 for ; Wed, 24 Jul 2019 12:39:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 42D7928814; Wed, 24 Jul 2019 12:39:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E5F2528803 for ; Wed, 24 Jul 2019 12:39:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=nQ3moKCGeWa+Un6mOm+ylb3hBvyAQNUGlxHlYpXbOSY=; b=ISxgkq5oEHZbGp+twUoLOUhlmA 84XUCMkXIL25sldPaCIPv+PtfLSgqCmgNmJ9eYy0IQkYq2Qykudn/9BxMheTqJayC7IEHYEXXIWLv Ce7HzEy+FBhkz5Dy/lccvCFyA08eegYsjNeuj6ANGTvsBkj34rXNFeOdUtkunfG5p2tPssJFryZX4 w+uq+OrZUPUxMv1l1+92GIeP0wBvEw/d5J0uKFQnz/V8UoxUrg7mgbEkztNDOX8Rr/jMpoIZ4kcHq 1AJk1ZPpX0HcYs6oC0zBn9/EEzhZZhw3t6c7MzVU1z+QNQioCN3mTUa9C3V/1AwzmWNTHJSvxPb7h P8hBzsFg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1hqGYK-0002sC-M4; Wed, 24 Jul 2019 12:39:28 +0000 Received: from inva021.nxp.com ([92.121.34.21]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1hqGXo-0002Pj-2C for linux-arm-kernel@lists.infradead.org; Wed, 24 Jul 2019 12:38:58 +0000 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 8FB2C20026B; Wed, 24 Jul 2019 14:38:52 +0200 (CEST) Received: from inva024.eu-rdc02.nxp.com (inva024.eu-rdc02.nxp.com [134.27.226.22]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 7FECC200265; Wed, 24 Jul 2019 14:38:52 +0200 (CEST) Received: from fsr-ub1864-112.ea.freescale.net (fsr-ub1864-112.ea.freescale.net [10.171.82.98]) by inva024.eu-rdc02.nxp.com (Postfix) with ESMTP id 40BB2205D8; Wed, 24 Jul 2019 14:38:51 +0200 (CEST) From: Leonard Crestez To: MyungJoo Ham , Kyungmin Park , Will Deacon , Stephen Boyd Subject: [RFCv3 1/3] dt-bindings: devfreq: Add initial bindings for i.MX Date: Wed, 24 Jul 2019 15:38:44 +0300 Message-Id: <93df6e7d81a404a43af684e2f96bdb6561ed87fe.1563971855.git.leonard.crestez@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190724_053856_381906_A5FCC05C X-CRM114-Status: GOOD ( 10.09 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Dong Aisheng , Mark Rutland , Fabio Estevam , Sascha Hauer , Jacky Bai , Anson Huang , linux-pm@vger.kernel.org, Viresh Kumar , Michael Turquette , Frank Li , NXP Linux Team , linux-kernel@vger.kernel.org, Chanwoo Choi , devicetree@vger.kernel.org, Rob Herring , Alexandre Bailon , Pengutronix Kernel Team , Shawn Guo , Georgi Djakov , linux-arm-kernel@lists.infradead.org, Abel Vesa MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Add initial dt bindings for the interconnects inside i.MX chips. Multiple external IPs are involved but SOC integration means the software controllable interfaces are very similar. This is initially only for imx8mm but add an "fsl,imx-bus" fallback similar to exynos-bus. Signed-off-by: Leonard Crestez --- .../devicetree/bindings/devfreq/imx.yaml | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 Documentation/devicetree/bindings/devfreq/imx.yaml diff --git a/Documentation/devicetree/bindings/devfreq/imx.yaml b/Documentation/devicetree/bindings/devfreq/imx.yaml new file mode 100644 index 000000000000..87f90cddfd29 --- /dev/null +++ b/Documentation/devicetree/bindings/devfreq/imx.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/devfreq/imx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic i.MX bus frequency device + +maintainers: + - Leonard Crestez + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and sometimes + voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied for + normal world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and Arteris + FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + reg: + maxItems: 1 + description: GPV area + + compatible: + contains: + enum: + - fsl,imx8m-noc + - fsl,imx8m-nic + - fsl,imx8m-ddrc + + clocks: + maxItems: 1 + +required: + - compatible + - clocks + +examples: + - | + #include + ddrc: dram-controller@3d400000 { + compatible = "fsl,imx8mm-ddrc"; + reg = <0x3d400000 0x400000>; + clocks = <&clk IMX8MM_CLK_DRAM>; + operating-points-v2 = <&ddrc_opp_table>; + }; + + - | + noc: noc@32700000 { + compatible = "fsl,imx8mm-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MM_CLK_NOC>; + operating-points-v2 = <&noc_opp_table>; + }; From patchwork Wed Jul 24 12:38:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 11056789 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F313D13AC for ; Wed, 24 Jul 2019 12:39:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E15B228803 for ; Wed, 24 Jul 2019 12:39:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D49E228814; Wed, 24 Jul 2019 12:39:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 5352E28803 for ; Wed, 24 Jul 2019 12:39:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=TEkjTWLjA7e7kDQF8R+e7qn63xyu+9Ot/3I6pdTms9k=; b=dKHf2kuxaLckBGEE5l/XhzJ1Bt OgKlgLL34bDbdQZIXOmqv4VGpnkficm+0yuXsURd4nhmtQDSVg0MoCV2IwJ0jwJueL32/nP/po7tJ 3iFZTHOc8idSBfproN1hXzG4Fqwzn/+jFk925eBpCuG3quy9t6tvMyNi66wEaa41FKzanlUYKQyDS URNgIoiqbyeg2OtORIbRUiYZUcV+Oi1L/jNJIvzLT/vBL1XWN7rM4SJhBde+mOX2HyYUqfMG2TCDb qROMPVBSpbAGuqyL48LqqMJWlOGaOILqFj6mMfdEx84Vh98C2fQvbAja1WGJxmMT7J2kmhfzq0hzL aHR7XkSw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1hqGYZ-000380-BI; Wed, 24 Jul 2019 12:39:43 +0000 Received: from inva020.nxp.com ([92.121.34.13]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1hqGXo-0002Pm-9N for linux-arm-kernel@lists.infradead.org; Wed, 24 Jul 2019 12:38:58 +0000 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id AD5491A0238; Wed, 24 Jul 2019 14:38:53 +0200 (CEST) Received: from inva024.eu-rdc02.nxp.com (inva024.eu-rdc02.nxp.com [134.27.226.22]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 9E3081A01C7; Wed, 24 Jul 2019 14:38:53 +0200 (CEST) Received: from fsr-ub1864-112.ea.freescale.net (fsr-ub1864-112.ea.freescale.net [10.171.82.98]) by inva024.eu-rdc02.nxp.com (Postfix) with ESMTP id 960AA205D8; Wed, 24 Jul 2019 14:38:52 +0200 (CEST) From: Leonard Crestez To: MyungJoo Ham , Kyungmin Park , Will Deacon , Stephen Boyd Subject: [RFCv3 2/3] PM / devfreq: Add imx driver Date: Wed, 24 Jul 2019 15:38:45 +0300 Message-Id: <8e74aef9a208c911f01b9de35c6f07e1f111b940.1563971855.git.leonard.crestez@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190724_053856_621131_32F6B821 X-CRM114-Status: GOOD ( 17.30 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Dong Aisheng , Mark Rutland , Fabio Estevam , Sascha Hauer , Jacky Bai , Anson Huang , linux-pm@vger.kernel.org, Viresh Kumar , Michael Turquette , Frank Li , NXP Linux Team , linux-kernel@vger.kernel.org, Chanwoo Choi , devicetree@vger.kernel.org, Rob Herring , Alexandre Bailon , Pengutronix Kernel Team , Shawn Guo , Georgi Djakov , linux-arm-kernel@lists.infradead.org, Abel Vesa MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Add initial support for frequency switching on pieces of the imx interconnect fabric. Uses clk_set_min_rate so that other subsytems can also impose minimum rate requests. Signed-off-by: Leonard Crestez --- drivers/devfreq/Kconfig | 10 +++ drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-devfreq.c | 143 ++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 drivers/devfreq/imx-devfreq.c diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index defe1d438710..dc3311ead538 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -90,10 +90,20 @@ config ARM_EXYNOS_BUS_DEVFREQ Each memory bus group could contain many memoby bus block. It reads PPMU counters of memory controllers by using DEVFREQ-event device and adjusts the operating frequencies and voltages with OPP support. This does not yet operate with optimal voltages. +config ARM_IMX_DEVFREQ + tristate "i.MX DEVFREQ Driver" + depends on ARCH_MXC || COMPILE_TEST + select DEVFREQ_GOV_USERSPACE + select PM_OPP + help + This adds the DEVFREQ driver for the i.MX family of SoCs. + It allows adjusting frequencies for DDRC (DDR Controller) and various + NICs and NOCs which form the SOC interconnect fabric + config ARM_TEGRA_DEVFREQ tristate "NVIDIA Tegra30/114/124/210 DEVFREQ Driver" depends on ARCH_TEGRA_3x_SOC || ARCH_TEGRA_114_SOC || \ ARCH_TEGRA_132_SOC || ARCH_TEGRA_124_SOC || \ ARCH_TEGRA_210_SOC || \ diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index 338ae8440db6..c2463ed4c934 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -7,10 +7,11 @@ obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Drivers diff --git a/drivers/devfreq/imx-devfreq.c b/drivers/devfreq/imx-devfreq.c new file mode 100644 index 000000000000..3ee2d37883c6 --- /dev/null +++ b/drivers/devfreq/imx-devfreq.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct imx_devfreq { + struct devfreq_dev_profile profile; + struct devfreq *devfreq; + struct clk *clk; +}; + +static int imx_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) +{ + struct imx_devfreq *priv = dev_get_drvdata(dev); + struct dev_pm_opp *new_opp; + unsigned long new_freq; + int ret; + + new_opp = devfreq_recommended_opp(dev, freq, flags); + if (IS_ERR(new_opp)) { + ret = PTR_ERR(new_opp); + dev_err(dev, "failed to get recommended opp: %d\n", ret); + return ret; + } + new_freq = dev_pm_opp_get_freq(new_opp); + dev_pm_opp_put(new_opp); + + ret = clk_set_min_rate(priv->clk, new_freq); + if (ret) + return ret; + + ret = clk_set_rate(priv->clk, 0); + if (ret) { + clk_set_min_rate(priv->clk, priv->devfreq->previous_freq); + return ret; + } + + return 0; +} + +static int imx_devfreq_get_cur_freq(struct device *dev, unsigned long *freq) +{ + struct imx_devfreq *priv = dev_get_drvdata(dev); + + *freq = clk_get_rate(priv->clk); + + return 0; +} + +static int imx_devfreq_get_dev_status(struct device *dev, + struct devfreq_dev_status *stat) +{ + struct imx_devfreq *priv = dev_get_drvdata(dev); + + stat->busy_time = 0; + stat->total_time = 0; + stat->current_frequency = clk_get_rate(priv->clk); + + return 0; +} + +static void imx_devfreq_exit(struct device *dev) +{ + return dev_pm_opp_of_remove_table(dev); +} + +static int imx_devfreq_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct imx_devfreq *priv; + const char *gov = DEVFREQ_GOV_USERSPACE; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->devfreq)) { + ret = PTR_ERR(priv->devfreq); + dev_err(dev, "failed to fetch clk: %d\n", ret); + return ret; + } + platform_set_drvdata(pdev, priv); + + ret = dev_pm_opp_of_add_table(dev); + if (ret < 0) { + dev_err(dev, "failed to get OPP table\n"); + return ret; + } + + priv->profile.polling_ms = 1000; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq = clk_get_rate(priv->clk); + + priv->devfreq = devm_devfreq_add_device(dev, &priv->profile, + gov, NULL); + if (IS_ERR(priv->devfreq)) { + ret = PTR_ERR(priv->devfreq); + dev_err(dev, "failed to add devfreq device: %d\n", ret); + goto err; + } + + return 0; + +err: + dev_pm_opp_of_remove_table(dev); + return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible = "fsl,imx8m-ddrc", }, + { .compatible = "fsl,imx8m-noc", }, + { .compatible = "fsl,imx8m-nic", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, imx_devfreq_of_match); + +static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name = "imx-devfreq", + .of_match_table = of_match_ptr(imx_devfreq_of_match), + }, +}; +module_platform_driver(imx_devfreq_platdrv); + +MODULE_DESCRIPTION("Generic i.MX bus frequency driver"); +MODULE_AUTHOR("Leonard Crestez "); +MODULE_LICENSE("GPL v2"); From patchwork Wed Jul 24 12:38:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 11056785 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7791E746 for ; Wed, 24 Jul 2019 12:39:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 64A9728803 for ; Wed, 24 Jul 2019 12:39:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 55DDC28817; Wed, 24 Jul 2019 12:39:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D33C528803 for ; Wed, 24 Jul 2019 12:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=kJ/bykAuXUlJbI3bdJjR1eD7IwARC8on1+mGN2wMTpc=; b=kOPUbXUQaC0bBrEwRL5z8QfdMw CN3zPdCyyp8YDZgUvIFZ1CM9uAjasxZRpsB1DqruaqUipJASVUmRQzkJ0MF3VaWsvx/uoUayv9RUE Wnneggxc8ZTID57XUsmPwRsA+ZKCPl4sbbNAU3aioa3HfDNduFpDQoABty9cbDUv4DrnRmy4lBwvD EkGPRSRGbnZ6LWvzSypDKbHwVPZrVtFM5V9SaoDX+doVR5qEDRifh0TDwZzmkQF+eY+DvEdVhLRa1 7nbLXstJGQs8PGlGNDB6reEQQ5Og1gFxlxDLoenRe9o+Wkebg5TlBouuV1V7XdwjejdCCNQky9n1F gIZNW0YA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1hqGXz-0002bJ-98; Wed, 24 Jul 2019 12:39:07 +0000 Received: from inva020.nxp.com ([92.121.34.13]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1hqGXn-0002Pw-Ua for linux-arm-kernel@lists.infradead.org; Wed, 24 Jul 2019 12:38:57 +0000 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id C01931A030E; Wed, 24 Jul 2019 14:38:54 +0200 (CEST) Received: from inva024.eu-rdc02.nxp.com (inva024.eu-rdc02.nxp.com [134.27.226.22]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id B22D81A02F9; Wed, 24 Jul 2019 14:38:54 +0200 (CEST) Received: from fsr-ub1864-112.ea.freescale.net (fsr-ub1864-112.ea.freescale.net [10.171.82.98]) by inva024.eu-rdc02.nxp.com (Postfix) with ESMTP id AFBA8205D8; Wed, 24 Jul 2019 14:38:53 +0200 (CEST) From: Leonard Crestez To: MyungJoo Ham , Kyungmin Park , Will Deacon , Stephen Boyd Subject: [RFCv3 3/3] PM / devfreq: Add imx perf event support Date: Wed, 24 Jul 2019 15:38:46 +0300 Message-Id: <72c89cd93817faf450ecd2d6e1d9c273198ff9ab.1563971855.git.leonard.crestez@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190724_053856_259577_520EC096 X-CRM114-Status: GOOD ( 16.16 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Dong Aisheng , Mark Rutland , Fabio Estevam , Sascha Hauer , Jacky Bai , Anson Huang , linux-pm@vger.kernel.org, Viresh Kumar , Michael Turquette , Frank Li , NXP Linux Team , linux-kernel@vger.kernel.org, Chanwoo Choi , devicetree@vger.kernel.org, Rob Herring , Alexandre Bailon , Pengutronix Kernel Team , Shawn Guo , Georgi Djakov , linux-arm-kernel@lists.infradead.org, Abel Vesa MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The imx8m ddrc has a performance monitoring block attached which can be used to measure bandwidth usage automatically adjust frequency. There is already a perf driver for that block so instead of implementing a devfreq events driver use the in-kernel perf API to fetch read/write bandwidth values and sum them. Signed-off-by: Leonard Crestez --- drivers/devfreq/imx-devfreq.c | 135 ++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/drivers/devfreq/imx-devfreq.c b/drivers/devfreq/imx-devfreq.c index 3ee2d37883c6..fd4c8ffb8b4a 100644 --- a/drivers/devfreq/imx-devfreq.c +++ b/drivers/devfreq/imx-devfreq.c @@ -11,14 +11,28 @@ #include #include #include #include +#include +#include + struct imx_devfreq { struct devfreq_dev_profile profile; struct devfreq *devfreq; struct clk *clk; + + struct platform_device* pmu_pdev; + struct pmu *pmu; + + struct perf_event_attr rd_event_attr; + struct perf_event_attr wr_event_attr; + struct perf_event *rd_event; + struct perf_event *wr_event; + + u64 last_rd_val, last_rd_ena, last_rd_run; + u64 last_wr_val, last_wr_ena, last_wr_run; }; static int imx_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) { struct imx_devfreq *priv = dev_get_drvdata(dev); @@ -64,22 +78,131 @@ static int imx_devfreq_get_dev_status(struct device *dev, stat->busy_time = 0; stat->total_time = 0; stat->current_frequency = clk_get_rate(priv->clk); + if (priv->rd_event && priv->wr_event) { + u64 rd_delta, rd_val, rd_ena, rd_run; + u64 wr_delta, wr_val, wr_ena, wr_run; + + rd_val = perf_event_read_value(priv->rd_event, &rd_ena, &rd_run); + wr_val = perf_event_read_value(priv->wr_event, &wr_ena, &wr_run); + + rd_delta = (rd_val - priv->last_rd_val) * (rd_ena - priv->last_rd_ena) / (rd_run - priv->last_rd_run); + priv->last_rd_val = rd_val; + priv->last_rd_ena = rd_ena; + priv->last_rd_run = rd_run; + wr_delta = (wr_val - priv->last_wr_val) * (wr_ena - priv->last_wr_ena) / (wr_run - priv->last_wr_run); + priv->last_wr_val = wr_val; + priv->last_wr_ena = wr_ena; + priv->last_wr_run = wr_run; + + /* magic numbers, possibly wrong */ + stat->busy_time = 4 * (rd_delta + wr_delta); + stat->total_time = stat->current_frequency; + + dev_dbg(dev, "perf load %02lu%% read=%lu write=%lu freq=%lu\n", + 100 * stat->busy_time / stat->total_time, + rd_delta, wr_delta, stat->current_frequency); + } + + return 0; +} + +static int imx_devfreq_perf_disable(struct imx_devfreq *priv) +{ + /* release and set to NULL */ + if (!IS_ERR_OR_NULL(priv->rd_event)) + perf_event_release_kernel(priv->rd_event); + if (!IS_ERR_OR_NULL(priv->wr_event)) + perf_event_release_kernel(priv->wr_event); + priv->rd_event = NULL; + priv->wr_event = NULL; + + return 0; +} + +static int imx_devfreq_perf_enable(struct imx_devfreq *priv) +{ + int ret; + + priv->rd_event_attr.size = sizeof(priv->rd_event_attr); + priv->rd_event_attr.type = priv->pmu->type; + priv->rd_event_attr.config = 0x2a; + + priv->rd_event = perf_event_create_kernel_counter( + &priv->rd_event_attr, 0, NULL, NULL, NULL); + if (IS_ERR(priv->rd_event)) { + ret = PTR_ERR(priv->rd_event); + goto err; + } + + priv->wr_event_attr.size = sizeof(priv->wr_event_attr); + priv->wr_event_attr.type = priv->pmu->type; + priv->wr_event_attr.config = 0x2b; + + priv->wr_event = perf_event_create_kernel_counter( + &priv->wr_event_attr, 0, NULL, NULL, NULL); + if (IS_ERR(priv->wr_event)) { + ret = PTR_ERR(priv->wr_event); + goto err; + } + return 0; + +err: + imx_devfreq_perf_disable(priv); + return ret; +} + +static int imx_devfreq_init_events(struct device *dev, + struct device_node* events_node) +{ + struct imx_devfreq *priv = dev_get_drvdata(dev); + struct device_driver *driver; + + /* + * We need pmu->type for perf_event_attr but there is no API for + * mapping device_node to pmu. Fetch private data for imx-ddr-pmu and + * cast that to a struct pmu instead. + */ + priv->pmu_pdev = of_find_device_by_node(events_node); + if (!priv->pmu_pdev) + return -ENOENT; + driver = priv->pmu_pdev->dev.driver; + if (!driver) + return -ENOENT; + if (strcmp(driver->name, "imx-ddr-pmu")) { + dev_warn(dev, "devfreq-events node %pOF has unexpected driver %s\n", + events_node, driver->name); + return -ENODEV; + } + + priv->pmu = platform_get_drvdata(priv->pmu_pdev); + if (!priv->pmu) + return -EPROBE_DEFER; + + dev_info(dev, "events from pmu %s\n", priv->pmu->name); + + return imx_devfreq_perf_enable(priv); } static void imx_devfreq_exit(struct device *dev) { + struct imx_devfreq *priv = dev_get_drvdata(dev); + + imx_devfreq_perf_disable(priv); + platform_device_put(priv->pmu_pdev); + return dev_pm_opp_of_remove_table(dev); } static int imx_devfreq_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct imx_devfreq *priv; + struct device_node *events_node; const char *gov = DEVFREQ_GOV_USERSPACE; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -104,10 +227,20 @@ static int imx_devfreq_probe(struct platform_device *pdev) priv->profile.get_dev_status = imx_devfreq_get_dev_status; priv->profile.exit = imx_devfreq_exit; priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; priv->profile.initial_freq = clk_get_rate(priv->clk); + /* Handle devfreq-events */ + events_node = of_parse_phandle(dev->of_node, "devfreq-events", 0); + if (events_node) { + ret = imx_devfreq_init_events(dev, events_node); + of_node_put(events_node); + if (ret) + goto err; + gov = DEVFREQ_GOV_SIMPLE_ONDEMAND; + } + priv->devfreq = devm_devfreq_add_device(dev, &priv->profile, gov, NULL); if (IS_ERR(priv->devfreq)) { ret = PTR_ERR(priv->devfreq); dev_err(dev, "failed to add devfreq device: %d\n", ret); @@ -115,10 +248,12 @@ static int imx_devfreq_probe(struct platform_device *pdev) } return 0; err: + imx_devfreq_perf_disable(priv); + platform_device_put(priv->pmu_pdev); dev_pm_opp_of_remove_table(dev); return ret; } static const struct of_device_id imx_devfreq_of_match[] = {