ipq806x: 5.15: replace fab scaling patch with devfreq driver
authorChristian Marangi <ansuelsmth@gmail.com>
Thu, 16 Jun 2022 20:18:49 +0000 (22:18 +0200)
committerChristian Marangi <ansuelsmth@gmail.com>
Tue, 11 Oct 2022 19:28:43 +0000 (21:28 +0200)
Replace fab scaling patch with devfreq driver.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
target/linux/ipq806x/patches-5.15/098-3-add-fab-scaling-support-with-cpufreq.patch [deleted file]
target/linux/ipq806x/patches-5.15/115-01-devfreq-add-ipq806x-fabric-scaling-driver.patch [new file with mode: 0644]
target/linux/ipq806x/patches-5.15/115-02-ARM-dts-qcom-add-fab-scaling-node-for-ipq806x.patch [new file with mode: 0644]

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 (file)
index 805979d..0000000
+++ /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 (file)
index 0000000..340c58a
--- /dev/null
@@ -0,0 +1,203 @@
+From 13f075999935bb696dbab63243923179f06fa05e Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@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@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@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 (file)
index 0000000..f4de1db
--- /dev/null
@@ -0,0 +1,48 @@
+From c3573f0907dadb0a6e9933aae2a46a489abcbd48 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@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@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@28100000 {
+                       compatible = "qcom,lpass-cpu";
+                       status = "disabled";