[openwrt/openwrt] ipq806x: 5.15: replace fab scaling patch with devfreq driver

LEDE Commits lede-commits at lists.infradead.org
Tue Oct 11 12:29:08 PDT 2022


ansuel pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/a8d7aed033cfe03fadf3c18459cf8b9302e7eefb

commit a8d7aed033cfe03fadf3c18459cf8b9302e7eefb
Author: Christian Marangi <ansuelsmth at gmail.com>
AuthorDate: Thu Jun 16 22:18:49 2022 +0200

    ipq806x: 5.15: replace fab scaling patch with devfreq driver
    
    Replace fab scaling patch with devfreq driver.
    
    Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 ...98-3-add-fab-scaling-support-with-cpufreq.patch | 243 ---------------------
 ...devfreq-add-ipq806x-fabric-scaling-driver.patch | 203 +++++++++++++++++
 ...dts-qcom-add-fab-scaling-node-for-ipq806x.patch |  48 ++++
 3 files changed, 251 insertions(+), 243 deletions(-)

diff --git a/target/linux/ipq806x/patches-5.15/098-3-add-fab-scaling-support-with-cpufreq.patch b/target/linux/ipq806x/patches-5.15/098-3-add-fab-scaling-support-with-cpufreq.patch
deleted file mode 100644
index 805979df8c..0000000000
--- a/target/linux/ipq806x/patches-5.15/098-3-add-fab-scaling-support-with-cpufreq.patch
+++ /dev/null
@@ -1,243 +0,0 @@
---- a/drivers/clk/qcom/Makefile
-+++ b/drivers/clk/qcom/Makefile
-@@ -15,6 +15,7 @@ clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-k
- clk-qcom-y += clk-hfpll.o
- clk-qcom-y += reset.o
- clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
-+clk-qcom-y += fab_scaling.o
- 
- # Keep alphabetically sorted by config
- obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
---- /dev/null
-+++ b/drivers/clk/qcom/fab_scaling.c
-@@ -0,0 +1,172 @@
-+/*
-+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/err.h>
-+#include <linux/io.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/slab.h>
-+#include <linux/fab_scaling.h>
-+
-+struct qcom_fab_scaling_data {
-+	u32 fab_freq_high;
-+	u32 fab_freq_nominal;
-+	u32 cpu_freq_threshold;
-+	struct clk *apps_fab_clk;
-+	struct clk *ddr_fab_clk;
-+};
-+
-+static struct qcom_fab_scaling_data *drv_data;
-+
-+int scale_fabrics(unsigned long max_cpu_freq)
-+{	
-+	struct clk *apps_fab_clk = drv_data->apps_fab_clk,
-+	           *ddr_fab_clk = drv_data->ddr_fab_clk;
-+	unsigned long target_freq, cur_freq;
-+	int ret;
-+
-+	/* Skip fab scaling if the driver is not ready */
-+	if (!apps_fab_clk || !ddr_fab_clk)
-+		return 0;
-+
-+	if (max_cpu_freq > drv_data->cpu_freq_threshold)
-+		target_freq = drv_data->fab_freq_high;
-+	else
-+		target_freq = drv_data->fab_freq_nominal;
-+
-+	cur_freq = clk_get_rate(ddr_fab_clk);
-+
-+	if (target_freq != cur_freq) {
-+		ret = clk_set_rate(apps_fab_clk, target_freq);
-+		if (ret)
-+			return ret;
-+		ret = clk_set_rate(ddr_fab_clk, target_freq);
-+		if (ret)
-+			return ret;
-+	}
-+
-+	return 0;
-+}
-+EXPORT_SYMBOL(scale_fabrics);
-+
-+static int ipq806x_fab_scaling_probe(struct platform_device *pdev)
-+{
-+	struct device_node *np = pdev->dev.of_node;
-+	struct clk *apps_fab_clk, *ddr_fab_clk;
-+	int ret;
-+
-+	if (!np)
-+		return -ENODEV;
-+	
-+	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
-+	if (!drv_data)
-+		return -ENOMEM;
-+
-+	if (of_property_read_u32(np, "fab_freq_high", &drv_data->fab_freq_high)) {
-+		pr_err("FABRICS turbo freq not found. Using defaults...\n");
-+		drv_data->fab_freq_high = 533000000;
-+	}
-+
-+	if (of_property_read_u32(np, "fab_freq_nominal", &drv_data->fab_freq_nominal)) {
-+		pr_err("FABRICS nominal freq not found. Using defaults...\n");
-+		drv_data->fab_freq_nominal = 400000000;
-+	}
-+
-+	if (of_property_read_u32(np, "cpu_freq_threshold", &drv_data->cpu_freq_threshold)) {
-+		pr_err("FABRICS cpu freq threshold not found. Using defaults...\n");
-+		drv_data->cpu_freq_threshold = 1000000000;
-+	}
-+
-+	apps_fab_clk = devm_clk_get(&pdev->dev, "apps-fab-clk");
-+	ret = PTR_ERR_OR_ZERO(apps_fab_clk);
-+	if (ret) {
-+		/*
-+		 * If apps fab clk node is present, but clock is not yet
-+		 * registered, we should try defering probe.
-+		 */
-+		if (ret != -EPROBE_DEFER) {
-+			pr_err("Failed to get APPS FABRIC clock: %d\n", ret);
-+			ret = -ENODEV;
-+		}
-+		goto err;
-+	}
-+
-+	clk_prepare_enable(apps_fab_clk);
-+	clk_set_rate(apps_fab_clk, drv_data->fab_freq_high);
-+	drv_data->apps_fab_clk = apps_fab_clk;
-+
-+	ddr_fab_clk = devm_clk_get(&pdev->dev, "ddr-fab-clk");
-+	ret = PTR_ERR_OR_ZERO(ddr_fab_clk);
-+	if (ret) {
-+		/*
-+		 * If ddr fab clk node is present, but clock is not yet
-+		 * registered, we should try defering probe.
-+		 */
-+		if (ret != -EPROBE_DEFER) {
-+			pr_err("Failed to get DDR FABRIC clock: %d\n", ret);
-+			ddr_fab_clk = NULL;
-+			ret = -ENODEV;
-+		}
-+		goto err;
-+	}
-+
-+	clk_prepare_enable(ddr_fab_clk);
-+	clk_set_rate(ddr_fab_clk, drv_data->fab_freq_high);
-+	drv_data->ddr_fab_clk = ddr_fab_clk;
-+
-+	return 0;
-+err:
-+	kfree(drv_data);
-+	return ret;
-+}
-+
-+static int ipq806x_fab_scaling_remove(struct platform_device *pdev)
-+{
-+	kfree(drv_data);
-+	return 0;
-+}
-+
-+static const struct of_device_id fab_scaling_ipq806x_match_table[] = {
-+	{ .compatible = "qcom,fab-scaling" },
-+	{ }
-+};
-+
-+static struct platform_driver fab_scaling_ipq806x_driver = {
-+	.probe		= ipq806x_fab_scaling_probe,
-+	.remove		= ipq806x_fab_scaling_remove,
-+	.driver		= {
-+		.name   = "fab-scaling",
-+		.of_match_table = fab_scaling_ipq806x_match_table,
-+	},
-+};
-+
-+static int __init fab_scaling_ipq806x_init(void)
-+{
-+	return platform_driver_register(&fab_scaling_ipq806x_driver);
-+}
-+late_initcall(fab_scaling_ipq806x_init);
-+
-+static void __exit fab_scaling_ipq806x_exit(void)
-+{
-+	platform_driver_unregister(&fab_scaling_ipq806x_driver);
-+}
-+module_exit(fab_scaling_ipq806x_exit);
---- /dev/null
-+++ b/include/linux/fab_scaling.h
-@@ -0,0 +1,31 @@
-+/*
-+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+
-+#ifndef __FAB_SCALING_H
-+#define __FAB_SCALING_H
-+
-+/**
-+ * scale_fabrics - Scale DDR and APPS FABRICS
-+ *
-+ * This function monitors all the registered clocks and does APPS
-+ * and DDR FABRIC scaling based on the idle frequencies with which
-+ * it was registered.
-+ *
-+ */
-+int scale_fabrics(unsigned long max_cpu_freq);
-+
-+#endif
---- a/drivers/cpufreq/qcom-cpufreq-krait.c
-+++ b/drivers/cpufreq/qcom-cpufreq-krait.c
-@@ -15,6 +15,7 @@
- #include <linux/regulator/consumer.h>
- #include <linux/slab.h>
- #include <linux/thermal.h>
-+#include <linux/fab_scaling.h>
- 
- #include "cpufreq-dt.h"
- 
-@@ -74,6 +75,13 @@ static int set_target(struct cpufreq_pol
- 			goto l2_scale_fail;
- 		}
- 
-+		/*
-+		 * Scale fabrics with max freq across all cores
-+		 */
-+		ret = scale_fabrics(target_freq);
-+		if (ret)
-+			goto l2_scale_fail;
-+
- 		opp = dev_pm_opp_find_level_exact(l2_dev, level);
- 		if (IS_ERR(opp)) {
- 			dev_err(l2_dev,
diff --git a/target/linux/ipq806x/patches-5.15/115-01-devfreq-add-ipq806x-fabric-scaling-driver.patch b/target/linux/ipq806x/patches-5.15/115-01-devfreq-add-ipq806x-fabric-scaling-driver.patch
new file mode 100644
index 0000000000..340c58a0c1
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.15/115-01-devfreq-add-ipq806x-fabric-scaling-driver.patch
@@ -0,0 +1,203 @@
+From 13f075999935bb696dbab63243923179f06fa05e Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at gmail.com>
+Date: Thu, 16 Jun 2022 19:56:08 +0200
+Subject: [PATCH 3/4] devfreq: add ipq806x fabric scaling driver
+
+Add ipq806x fabric scaling driver using the devfreq passive governor.
+
+Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
+---
+ drivers/devfreq/Kconfig               |  11 ++
+ drivers/devfreq/Makefile              |   1 +
+ drivers/devfreq/ipq806x-fab-devfreq.c | 155 ++++++++++++++++++++++++++
+ 3 files changed, 167 insertions(+)
+ create mode 100644 drivers/devfreq/ipq806x-fab-devfreq.c
+
+--- a/drivers/devfreq/Kconfig
++++ b/drivers/devfreq/Kconfig
+@@ -143,6 +143,17 @@ config ARM_KRAIT_CACHE_DEVFREQ
+ 	  based on the max frequency across all core and the range set in the device
+ 	  dts. If provided this scale also the regulator attached to the l2 cache.
+ 
++config ARM_IPQ806X_FAB_DEVFREQ
++	tristate "Scaling support for ipq806x Soc Fabric"
++	depends on ARCH_QCOM || COMPILE_TEST
++	select DEVFREQ_GOV_PASSIVE
++	help
++	  This adds the DEVFREQ driver for the ipq806x Soc Fabric.
++
++	  The driver register with the cpufreq notifier and find the right frequency
++	  based on the max frequency across all core and the range set in the device
++	  dts.
++
+ source "drivers/devfreq/event/Kconfig"
+ 
+ endif # PM_DEVFREQ
+--- a/drivers/devfreq/Makefile
++++ b/drivers/devfreq/Makefile
+@@ -14,6 +14,7 @@ obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ)	+=
+ obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
+ obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra30-devfreq.o
+ obj-$(CONFIG_ARM_KRAIT_CACHE_DEVFREQ)	+= krait-cache-devfreq.o
++obj-$(CONFIG_ARM_IPQ806X_FAB_DEVFREQ)	+= ipq806x-fab-devfreq.o
+ 
+ # DEVFREQ Event Drivers
+ obj-$(CONFIG_PM_DEVFREQ_EVENT)		+= event/
+--- /dev/null
++++ b/drivers/devfreq/ipq806x-fab-devfreq.c
+@@ -0,0 +1,155 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/cpufreq.h>
++#include <linux/devfreq.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/slab.h>
++#include <linux/pm_opp.h>
++
++#include "governor.h"
++
++struct ipq806x_fab_data {
++	struct clk *fab_clk;
++	struct clk *ddr_clk;
++};
++
++static int ipq806x_fab_get_cur_freq(struct device *dev, unsigned long *freq)
++{
++	struct ipq806x_fab_data *data = dev_get_drvdata(dev);
++
++	*freq = clk_get_rate(data->fab_clk);
++
++	return 0;
++};
++
++static int ipq806x_fab_target(struct device *dev, unsigned long *freq,
++			      u32 flags)
++{
++	struct ipq806x_fab_data *data = dev_get_drvdata(dev);
++	struct dev_pm_opp *opp;
++	int ret;
++
++	opp = dev_pm_opp_find_freq_ceil(dev, freq);
++	if (unlikely(IS_ERR(opp)))
++		return PTR_ERR(opp);
++
++	dev_pm_opp_put(opp);
++
++	ret = clk_set_rate(data->fab_clk, *freq);
++	if (ret)
++		return ret;
++
++	return clk_set_rate(data->ddr_clk, *freq);
++};
++
++static int ipq806x_fab_get_dev_status(struct device *dev,
++				      struct devfreq_dev_status *stat)
++{
++	struct ipq806x_fab_data *data = dev_get_drvdata(dev);
++
++	stat->busy_time = 0;
++	stat->total_time = 0;
++	stat->current_frequency = clk_get_rate(data->fab_clk);
++
++	return 0;
++};
++
++static struct devfreq_dev_profile ipq806x_fab_devfreq_profile = {
++	.target = ipq806x_fab_target,
++	.get_dev_status = ipq806x_fab_get_dev_status,
++	.get_cur_freq = ipq806x_fab_get_cur_freq
++};
++
++static struct devfreq_passive_data devfreq_gov_data = {
++	.parent_type = CPUFREQ_PARENT_DEV,
++};
++
++static int ipq806x_fab_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	struct ipq806x_fab_data *data;
++	struct devfreq *devfreq;
++	struct clk *clk;
++	int ret;
++
++	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
++	clk = devm_clk_get(dev, "apps-fab-clk");
++	if (IS_ERR(clk)) {
++		dev_err_probe(dev, PTR_ERR(clk), "failed to get apps fab clk\n");
++		return PTR_ERR(clk);
++	}
++
++	clk_prepare_enable(clk);
++	data->fab_clk = clk;
++
++	clk = devm_clk_get(dev, "ddr-fab-clk");
++	if (IS_ERR(clk)) {
++		dev_err_probe(dev, PTR_ERR(clk), "failed to get ddr fab clk\n");
++		goto err_ddr;
++	}
++
++	clk_prepare_enable(clk);
++	data->ddr_clk = clk;
++
++	ret = dev_pm_opp_of_add_table(dev);
++	if (ret) {
++		dev_err(dev, "failed to parse fab freq thresholds\n");
++		return ret;
++	}
++
++	dev_set_drvdata(dev, data);
++
++	devfreq = devm_devfreq_add_device(&pdev->dev, &ipq806x_fab_devfreq_profile,
++					  DEVFREQ_GOV_PASSIVE, &devfreq_gov_data);
++	if (IS_ERR(devfreq))
++		dev_pm_opp_remove_table(dev);
++
++	return PTR_ERR_OR_ZERO(devfreq);
++
++err_ddr:
++	clk_unprepare(data->fab_clk);
++	clk_put(data->fab_clk);
++	return PTR_ERR(clk);
++};
++
++static int ipq806x_fab_remove(struct platform_device *pdev)
++{
++	struct ipq806x_fab_data *data = dev_get_drvdata(&pdev->dev);
++
++	clk_unprepare(data->fab_clk);
++	clk_put(data->fab_clk);
++
++	clk_unprepare(data->ddr_clk);
++	clk_put(data->ddr_clk);
++
++	dev_pm_opp_remove_table(&pdev->dev);
++
++	return 0;
++};
++
++static const struct of_device_id ipq806x_fab_match_table[] = {
++	{ .compatible = "qcom,fab-scaling" },
++	{}
++};
++
++static struct platform_driver ipq806x_fab_driver = {
++	.probe		= ipq806x_fab_probe,
++	.remove		= ipq806x_fab_remove,
++	.driver		= {
++		.name   = "ipq806x-fab-scaling",
++		.of_match_table = ipq806x_fab_match_table,
++	},
++};
++module_platform_driver(ipq806x_fab_driver);
++
++MODULE_DESCRIPTION("ipq806x Fab Scaling driver");
++MODULE_AUTHOR("Christian Marangi <ansuelsmth at gmail.com>");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/ipq806x/patches-5.15/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch b/target/linux/ipq806x/patches-5.15/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch
new file mode 100644
index 0000000000..f4de1dbb52
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.15/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch
@@ -0,0 +1,48 @@
+From c3573f0907dadb0a6e9933aae2a46a489abcbd48 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at gmail.com>
+Date: Thu, 16 Jun 2022 20:03:05 +0200
+Subject: [PATCH 4/4] ARM: dts: qcom: add fab scaling node for ipq806x
+
+Add fabric scaling node for ipq806x to correctly scale apps and ddr
+fabric clk.
+
+Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
+---
+ arch/arm/boot/dts/qcom-ipq8064.dtsi | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
+@@ -170,6 +170,18 @@
+ 		};
+ 	};
+ 
++	opp_table_fab: opp_table_fab {
++		compatible = "operating-points-v2";
++
++		opp-533000000 {
++			opp-hz = /bits/ 64 <533000000>;
++		};
++
++		opp-400000000 {
++			opp-hz = /bits/ 64 <400000000>;
++		};
++	};
++
+ 	thermal-zones {
+ 		tsens_tz_sensor0 {
+ 			polling-delay-passive = <0>;
+@@ -470,6 +482,13 @@
+ 			operating-points-v2 = <&opp_table_l2>;
+ 		};
+ 
++		fab-scaling {
++			compatible = "qcom,fab-scaling";
++			clocks = <&rpmcc RPM_APPS_FABRIC_A_CLK>, <&rpmcc RPM_EBI1_A_CLK>;
++			clock-names = "apps-fab-clk", "ddr-fab-clk";
++			operating-points-v2 = <&opp_table_fab>;
++		};
++
+ 		lpass at 28100000 {
+ 			compatible = "qcom,lpass-cpu";
+ 			status = "disabled";




More information about the lede-commits mailing list