airoha: an7581: refresh and fix cpufreq patch
authorChristian Marangi <ansuelsmth@gmail.com>
Mon, 27 Jan 2025 10:07:13 +0000 (11:07 +0100)
committerChristian Marangi <ansuelsmth@gmail.com>
Mon, 27 Jan 2025 10:07:13 +0000 (11:07 +0100)
Refresh cpufreq with merged upstream version. Also fix the PM Domain
rebased patch to correctly expose the symbol for non Mediatek target.

Update dtsi with new pm domain name.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
target/linux/airoha/an7581/config-6.6
target/linux/airoha/dts/an7581.dtsi
target/linux/airoha/patches-6.6/039-v6.14-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch [new file with mode: 0644]
target/linux/airoha/patches-6.6/040-v6.14-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch [new file with mode: 0644]
target/linux/airoha/patches-6.6/100-01-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch [deleted file]
target/linux/airoha/patches-6.6/100-02-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch [deleted file]

index f80bf49f8c11907e7bee8b25afcc9f297a519c48..d86aa8bbbbb0412247b50706639367b73367e155 100644 (file)
@@ -1,4 +1,5 @@
 CONFIG_64BIT=y
+CONFIG_AIROHA_CPU_PM_DOMAIN=y
 CONFIG_AIROHA_THERMAL=y
 CONFIG_AIROHA_WATCHDOG=y
 CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y
index 820ab0bfa8fb41bf7e6c7caeaf56b46848d78a7a..2b4c1b716bec6eec3f5123eee7b7a40db6d6ad68 100644 (file)
@@ -81,7 +81,7 @@
                        clocks = <&cpufreq>;
                        clock-names = "cpu";
                        power-domains = <&cpufreq>;
-                       power-domain-names = "cpu_pd";
+                       power-domain-names = "perf";
                        next-level-cache = <&l2>;
                        #cooling-cells = <2>;
                };
@@ -95,7 +95,7 @@
                        clocks = <&cpufreq>;
                        clock-names = "cpu";
                        power-domains = <&cpufreq>;
-                       power-domain-names = "cpu_pd";
+                       power-domain-names = "perf";
                        next-level-cache = <&l2>;
                        #cooling-cells = <2>;
                };
                        clocks = <&cpufreq>;
                        clock-names = "cpu";
                        power-domains = <&cpufreq>;
-                       power-domain-names = "cpu_pd";
+                       power-domain-names = "perf";
                        next-level-cache = <&l2>;
                        #cooling-cells = <2>;
                };
                        clocks = <&cpufreq>;
                        clock-names = "cpu";
                        power-domains = <&cpufreq>;
-                       power-domain-names = "cpu_pd";
+                       power-domain-names = "perf";
                        next-level-cache = <&l2>;
                        #cooling-cells = <2>;
                };
diff --git a/target/linux/airoha/patches-6.6/039-v6.14-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch b/target/linux/airoha/patches-6.6/039-v6.14-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch
new file mode 100644 (file)
index 0000000..0db82d5
--- /dev/null
@@ -0,0 +1,232 @@
+From 84cf9e541cccb8cb698518a9897942e8c78f1d83 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Thu, 9 Jan 2025 14:12:58 +0100
+Subject: [PATCH] cpufreq: airoha: Add EN7581 CPUFreq SMCCC driver
+
+Add simple CPU Freq driver for Airoha EN7581 SoC that control CPU
+frequency scaling with SMC APIs and register a generic "cpufreq-dt"
+device.
+
+All CPU share the same frequency and can't be controlled independently.
+CPU frequency is controlled by the attached PM domain.
+
+Add SoC compatible to cpufreq-dt-plat block list as a dedicated cpufreq
+driver is needed with OPP v2 nodes declared in DTS.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+---
+ drivers/cpufreq/Kconfig.arm          |   8 ++
+ drivers/cpufreq/Makefile             |   1 +
+ drivers/cpufreq/airoha-cpufreq.c     | 152 +++++++++++++++++++++++++++
+ drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
+ 4 files changed, 163 insertions(+)
+ create mode 100644 drivers/cpufreq/airoha-cpufreq.c
+
+--- a/drivers/cpufreq/Kconfig.arm
++++ b/drivers/cpufreq/Kconfig.arm
+@@ -41,6 +41,14 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVME
+         To compile this driver as a module, choose M here: the
+         module will be called sun50i-cpufreq-nvmem.
++config ARM_AIROHA_SOC_CPUFREQ
++      tristate "Airoha EN7581 SoC CPUFreq support"
++      depends on ARCH_AIROHA || COMPILE_TEST
++      select PM_OPP
++      default ARCH_AIROHA
++      help
++        This adds the CPUFreq driver for Airoha EN7581 SoCs.
++
+ config ARM_APPLE_SOC_CPUFREQ
+       tristate "Apple Silicon SoC CPUFreq support"
+       depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)
+--- a/drivers/cpufreq/Makefile
++++ b/drivers/cpufreq/Makefile
+@@ -52,6 +52,7 @@ obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY)       +
+ ##################################################################################
+ # ARM SoC drivers
++obj-$(CONFIG_ARM_AIROHA_SOC_CPUFREQ)  += airoha-cpufreq.o
+ obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ)   += apple-soc-cpufreq.o
+ obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
+ obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ)   += armada-8k-cpufreq.o
+--- /dev/null
++++ b/drivers/cpufreq/airoha-cpufreq.c
+@@ -0,0 +1,166 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/bitfield.h>
++#include <linux/cpufreq.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/slab.h>
++
++#include "cpufreq-dt.h"
++
++struct airoha_cpufreq_priv {
++      int opp_token;
++      struct device **virt_devs;
++      struct platform_device *cpufreq_dt;
++};
++
++static struct platform_device *cpufreq_pdev;
++
++/* NOP function to disable OPP from setting clock */
++static int airoha_cpufreq_config_clks_nop(struct device *dev,
++                                        struct opp_table *opp_table,
++                                        struct dev_pm_opp *old_opp,
++                                        struct dev_pm_opp *opp,
++                                        void *data, bool scaling_down)
++{
++      return 0;
++}
++
++static const char * const airoha_cpufreq_clk_names[] = { "cpu", NULL };
++static const char * const airoha_cpufreq_pd_names[] = { "perf", NULL };
++
++static int airoha_cpufreq_probe(struct platform_device *pdev)
++{
++      struct dev_pm_opp_config config = {
++              .clk_names = airoha_cpufreq_clk_names,
++              .config_clks = airoha_cpufreq_config_clks_nop,
++              .genpd_names = airoha_cpufreq_pd_names,
++      };
++      struct platform_device *cpufreq_dt;
++      struct airoha_cpufreq_priv *priv;
++      struct device *dev = &pdev->dev;
++      struct device **virt_devs = NULL;
++      struct device *cpu_dev;
++      int ret;
++
++      /* CPUs refer to the same OPP table */
++      cpu_dev = get_cpu_device(0);
++      if (!cpu_dev)
++              return -ENODEV;
++
++      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      /* Set OPP table conf with NOP config_clks */
++      priv->opp_token = dev_pm_opp_set_config(cpu_dev, &config);
++      if (priv->opp_token < 0)
++              return dev_err_probe(dev, priv->opp_token, "Failed to set OPP config\n");
++
++      /* Set Attached PM for OPP ACTIVE */
++      if (virt_devs) {
++              const char * const *name = airoha_cpufreq_pd_names;
++              int i, j;
++
++              for (i = 0; *name; i++, name++) {
++                      ret = pm_runtime_resume_and_get(virt_devs[i]);
++                      if (ret) {
++                              dev_err(cpu_dev, "failed to resume %s: %d\n",
++                                      *name, ret);
++
++                              /* Rollback previous PM runtime calls */
++                              name = config.genpd_names;
++                              for (j = 0; *name && j < i; j++, name++)
++                                      pm_runtime_put(virt_devs[j]);
++
++                              goto err_register_cpufreq;
++                      }
++              }
++              priv->virt_devs = virt_devs;
++      }
++
++      cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
++      ret = PTR_ERR_OR_ZERO(cpufreq_dt);
++      if (ret) {
++              dev_err(dev, "failed to create cpufreq-dt device: %d\n", ret);
++              goto err_register_cpufreq;
++      }
++
++      priv->cpufreq_dt = cpufreq_dt;
++      platform_set_drvdata(pdev, priv);
++
++      return 0;
++
++err_register_cpufreq:
++      dev_pm_opp_clear_config(priv->opp_token);
++
++      return ret;
++}
++
++static void airoha_cpufreq_remove(struct platform_device *pdev)
++{
++      struct airoha_cpufreq_priv *priv = platform_get_drvdata(pdev);
++      const char * const *name = airoha_cpufreq_pd_names;
++      int i;
++
++      platform_device_unregister(priv->cpufreq_dt);
++
++      dev_pm_opp_clear_config(priv->opp_token);
++
++      for (i = 0; *name; i++, name++)
++              pm_runtime_put(priv->virt_devs[i]);
++}
++
++static struct platform_driver airoha_cpufreq_driver = {
++      .probe = airoha_cpufreq_probe,
++      .remove_new = airoha_cpufreq_remove,
++      .driver = {
++              .name = "airoha-cpufreq",
++      },
++};
++
++static const struct of_device_id airoha_cpufreq_match_list[] __initconst = {
++      { .compatible = "airoha,en7581" },
++      {},
++};
++MODULE_DEVICE_TABLE(of, airoha_cpufreq_match_list);
++
++static int __init airoha_cpufreq_init(void)
++{
++      struct device_node *np = of_find_node_by_path("/");
++      const struct of_device_id *match;
++      int ret;
++
++      if (!np)
++              return -ENODEV;
++
++      match = of_match_node(airoha_cpufreq_match_list, np);
++      of_node_put(np);
++      if (!match)
++              return -ENODEV;
++
++      ret = platform_driver_register(&airoha_cpufreq_driver);
++      if (unlikely(ret < 0))
++              return ret;
++
++      cpufreq_pdev = platform_device_register_data(NULL, "airoha-cpufreq",
++                                                   -1, match, sizeof(*match));
++      ret = PTR_ERR_OR_ZERO(cpufreq_pdev);
++      if (ret)
++              platform_driver_unregister(&airoha_cpufreq_driver);
++
++      return ret;
++}
++module_init(airoha_cpufreq_init);
++
++static void __exit airoha_cpufreq_exit(void)
++{
++      platform_device_unregister(cpufreq_pdev);
++      platform_driver_unregister(&airoha_cpufreq_driver);
++}
++module_exit(airoha_cpufreq_exit);
++
++MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
++MODULE_DESCRIPTION("CPUfreq driver for Airoha SoCs");
++MODULE_LICENSE("GPL");
+--- a/drivers/cpufreq/cpufreq-dt-platdev.c
++++ b/drivers/cpufreq/cpufreq-dt-platdev.c
+@@ -103,6 +103,8 @@ static const struct of_device_id allowli
+  * platforms using "operating-points-v2" property.
+  */
+ static const struct of_device_id blocklist[] __initconst = {
++      { .compatible = "airoha,en7581", },
++
+       { .compatible = "allwinner,sun50i-h6", },
+       { .compatible = "apple,arm-platform", },
diff --git a/target/linux/airoha/patches-6.6/040-v6.14-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch b/target/linux/airoha/patches-6.6/040-v6.14-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch
new file mode 100644 (file)
index 0000000..8dc8a3d
--- /dev/null
@@ -0,0 +1,196 @@
+From 82e703dd438b71432cc0ccbb90925d1e32dd014a Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Thu, 9 Jan 2025 14:12:57 +0100
+Subject: [PATCH] pmdomain: airoha: Add Airoha CPU PM Domain support
+
+Add Airoha CPU PM Domain support to control frequency and power of CPU
+present on Airoha EN7581 SoC.
+
+Frequency and power can be controlled with the use of the SMC command by
+passing the performance state. The driver also expose a read-only clock
+that expose the current CPU frequency with SMC command.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Link: https://lore.kernel.org/r/20250109131313.32317-1-ansuelsmth@gmail.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/pmdomain/mediatek/Kconfig             |  12 ++
+ drivers/pmdomain/mediatek/Makefile            |   1 +
+ .../pmdomain/mediatek/airoha-cpu-pmdomain.c   | 144 ++++++++++++++++++
+ 3 files changed, 157 insertions(+)
+ create mode 100644 drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
+
+--- a/drivers/soc/mediatek/Kconfig
++++ b/drivers/soc/mediatek/Kconfig
+@@ -2,6 +2,17 @@
+ #
+ # MediaTek SoC drivers
+ #
++config AIROHA_CPU_PM_DOMAIN
++      tristate "Airoha CPU power domain"
++      default ARCH_AIROHA
++      depends on PM
++      select PM_GENERIC_DOMAINS
++      help
++        Say y here to enable CPU power domain support for Airoha SoC.
++
++        CPU frequency and power is controlled by ATF with SMC command to
++        set performance states.
++
+ menu "MediaTek SoC drivers"
+       depends on ARCH_MEDIATEK || COMPILE_TEST
+--- a/drivers/pmdomain/mediatek/Makefile
++++ b/drivers/pmdomain/mediatek/Makefile
+@@ -1,3 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_MTK_SCPSYS)              += mtk-scpsys.o
+ obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS)   += mtk-pm-domains.o
++obj-$(CONFIG_AIROHA_CPU_PM_DOMAIN)    += airoha-cpu-pmdomain.o
+--- /dev/null
++++ b/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
+@@ -0,0 +1,144 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/arm-smccc.h>
++#include <linux/bitfield.h>
++#include <linux/clk-provider.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pm_domain.h>
++#include <linux/slab.h>
++
++#define AIROHA_SIP_AVS_HANDLE                 0x82000301
++#define AIROHA_AVS_OP_BASE                    0xddddddd0
++#define AIROHA_AVS_OP_MASK                    GENMASK(1, 0)
++#define AIROHA_AVS_OP_FREQ_DYN_ADJ            (AIROHA_AVS_OP_BASE | \
++                                               FIELD_PREP(AIROHA_AVS_OP_MASK, 0x1))
++#define AIROHA_AVS_OP_GET_FREQ                        (AIROHA_AVS_OP_BASE | \
++                                               FIELD_PREP(AIROHA_AVS_OP_MASK, 0x2))
++
++struct airoha_cpu_pmdomain_priv {
++      struct clk_hw hw;
++      struct generic_pm_domain pd;
++};
++
++static long airoha_cpu_pmdomain_clk_round(struct clk_hw *hw, unsigned long rate,
++                                        unsigned long *parent_rate)
++{
++      return rate;
++}
++
++static unsigned long airoha_cpu_pmdomain_clk_get(struct clk_hw *hw,
++                                               unsigned long parent_rate)
++{
++      struct arm_smccc_res res;
++
++      arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_GET_FREQ,
++                           0, 0, 0, 0, 0, 0, &res);
++
++      /* SMCCC returns freq in MHz */
++      return (int)(res.a0 * 1000 * 1000);
++}
++
++/* Airoha CPU clk SMCC is always enabled */
++static int airoha_cpu_pmdomain_clk_is_enabled(struct clk_hw *hw)
++{
++      return true;
++}
++
++static const struct clk_ops airoha_cpu_pmdomain_clk_ops = {
++      .recalc_rate = airoha_cpu_pmdomain_clk_get,
++      .is_enabled = airoha_cpu_pmdomain_clk_is_enabled,
++      .round_rate = airoha_cpu_pmdomain_clk_round,
++};
++
++static int airoha_cpu_pmdomain_set_performance_state(struct generic_pm_domain *domain,
++                                                   unsigned int state)
++{
++      struct arm_smccc_res res;
++
++      arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_FREQ_DYN_ADJ,
++                           0, state, 0, 0, 0, 0, &res);
++
++      /* SMC signal correct apply by unsetting BIT 0 */
++      return res.a0 & BIT(0) ? -EINVAL : 0;
++}
++
++static int airoha_cpu_pmdomain_probe(struct platform_device *pdev)
++{
++      struct airoha_cpu_pmdomain_priv *priv;
++      struct device *dev = &pdev->dev;
++      const struct clk_init_data init = {
++              .name = "cpu",
++              .ops = &airoha_cpu_pmdomain_clk_ops,
++              /* Clock with no set_rate, can't cache */
++              .flags = CLK_GET_RATE_NOCACHE,
++      };
++      struct generic_pm_domain *pd;
++      int ret;
++
++      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      /* Init and register a get-only clk for Cpufreq */
++      priv->hw.init = &init;
++      ret = devm_clk_hw_register(dev, &priv->hw);
++      if (ret)
++              return ret;
++
++      ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
++                                        &priv->hw);
++      if (ret)
++              return ret;
++
++      /* Init and register a PD for CPU */
++      pd = &priv->pd;
++      pd->name = "cpu_pd";
++      pd->flags = GENPD_FLAG_ALWAYS_ON;
++      pd->set_performance_state = airoha_cpu_pmdomain_set_performance_state;
++
++      ret = pm_genpd_init(pd, NULL, false);
++      if (ret)
++              return ret;
++
++      ret = of_genpd_add_provider_simple(dev->of_node, pd);
++      if (ret)
++              goto err_add_provider;
++
++      platform_set_drvdata(pdev, priv);
++
++      return 0;
++
++err_add_provider:
++      pm_genpd_remove(pd);
++
++      return ret;
++}
++
++static void airoha_cpu_pmdomain_remove(struct platform_device *pdev)
++{
++      struct airoha_cpu_pmdomain_priv *priv = platform_get_drvdata(pdev);
++
++      of_genpd_del_provider(pdev->dev.of_node);
++      pm_genpd_remove(&priv->pd);
++}
++
++static const struct of_device_id airoha_cpu_pmdomain_of_match[] = {
++      { .compatible = "airoha,en7581-cpufreq" },
++      { },
++};
++MODULE_DEVICE_TABLE(of, airoha_cpu_pmdomain_of_match);
++
++static struct platform_driver airoha_cpu_pmdomain_driver = {
++      .probe = airoha_cpu_pmdomain_probe,
++      .remove_new = airoha_cpu_pmdomain_remove,
++      .driver = {
++              .name = "airoha-cpu-pmdomain",
++              .of_match_table = airoha_cpu_pmdomain_of_match,
++      },
++};
++module_platform_driver(airoha_cpu_pmdomain_driver);
++
++MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
++MODULE_DESCRIPTION("CPU PM domain driver for Airoha SoCs");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/airoha/patches-6.6/100-01-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch b/target/linux/airoha/patches-6.6/100-01-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch
deleted file mode 100644 (file)
index 52d3f40..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-From 76e4e6ce9aaae897f80e375345bf0095e1b09ff2 Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth@gmail.com>
-Date: Sat, 4 Jan 2025 19:03:09 +0100
-Subject: [PATCH v9 1/2] pmdomain: airoha: Add Airoha CPU PM Domain support
-
-Add Airoha CPU PM Domain support to control frequency and power of CPU
-present on Airoha EN7581 SoC.
-
-Frequency and power can be controlled with the use of the SMC command by
-passing the performance state. The driver also expose a read-only clock
-that expose the current CPU frequency with SMC command.
-
-Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
----
-Changes v9:
-- Fix compile error targetting wrong branch (remove_new change)
-Changes v8:
-- Add this patch
-- Use SMC invoke instead of 1.2
-
- drivers/pmdomain/mediatek/Kconfig             |  11 ++
- drivers/pmdomain/mediatek/Makefile            |   1 +
- .../pmdomain/mediatek/airoha-cpu-pmdomain.c   | 144 ++++++++++++++++++
- 3 files changed, 156 insertions(+)
- create mode 100644 drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
-
---- a/drivers/soc/mediatek/Kconfig
-+++ b/drivers/soc/mediatek/Kconfig
-@@ -72,6 +72,17 @@ config MTK_SCPSYS_PM_DOMAINS
-         Control Processor System (SCPSYS) has several power management related
-         tasks in the system.
-+config AIROHA_CPU_PM_DOMAIN
-+      tristate "Airoha CPU power domain"
-+      default ARCH_AIROHA
-+      depends on PM
-+      select PM_GENERIC_DOMAINS
-+      help
-+        Say y here to enable CPU power domain support for Airoha SoC.
-+
-+        CPU frequency and power is controlled by ATF with SMC command to
-+        set performance states.
-+
- config MTK_MMSYS
-       tristate "MediaTek MMSYS Support"
-       default ARCH_MEDIATEK
---- a/drivers/pmdomain/mediatek/Makefile
-+++ b/drivers/pmdomain/mediatek/Makefile
-@@ -1,3 +1,4 @@
- # SPDX-License-Identifier: GPL-2.0-only
- obj-$(CONFIG_MTK_SCPSYS)              += mtk-scpsys.o
- obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS)   += mtk-pm-domains.o
-+obj-$(CONFIG_AIROHA_CPU_PM_DOMAIN)    += airoha-cpu-pmdomain.o
---- /dev/null
-+++ b/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
-@@ -0,0 +1,145 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+#include <linux/arm-smccc.h>
-+#include <linux/bitfield.h>
-+#include <linux/clk-provider.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_domain.h>
-+#include <linux/slab.h>
-+
-+#define AIROHA_SIP_AVS_HANDLE                 0x82000301
-+#define AIROHA_AVS_OP_BASE                    0xddddddd0
-+#define AIROHA_AVS_OP_MASK                    GENMASK(1, 0)
-+#define AIROHA_AVS_OP_FREQ_DYN_ADJ            (AIROHA_AVS_OP_BASE | \
-+                                               FIELD_PREP(AIROHA_AVS_OP_MASK, 0x1))
-+#define AIROHA_AVS_OP_GET_FREQ                        (AIROHA_AVS_OP_BASE | \
-+                                               FIELD_PREP(AIROHA_AVS_OP_MASK, 0x2))
-+
-+struct airoha_cpu_pmdomain_priv {
-+      struct clk_hw hw;
-+      struct generic_pm_domain pd;
-+};
-+
-+static long airoha_cpu_pmdomain_clk_round(struct clk_hw *hw, unsigned long rate,
-+                                        unsigned long *parent_rate)
-+{
-+      return rate;
-+}
-+
-+static unsigned long airoha_cpu_pmdomain_clk_get(struct clk_hw *hw,
-+                                               unsigned long parent_rate)
-+{
-+      struct arm_smccc_res res;
-+
-+      arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_GET_FREQ,
-+                           0, 0, 0, 0, 0, 0, &res);
-+
-+      /* SMCCC returns freq in MHz */
-+      return (int)(res.a0 * 1000 * 1000);
-+}
-+
-+/* Airoha CPU clk SMCC is always enabled */
-+static int airoha_cpu_pmdomain_clk_is_enabled(struct clk_hw *hw)
-+{
-+      return true;
-+}
-+
-+static const struct clk_ops airoha_cpu_pmdomain_clk_ops = {
-+      .recalc_rate = airoha_cpu_pmdomain_clk_get,
-+      .is_enabled = airoha_cpu_pmdomain_clk_is_enabled,
-+      .round_rate = airoha_cpu_pmdomain_clk_round,
-+};
-+
-+static int airoha_cpu_pmdomain_set_performance_state(struct generic_pm_domain *domain,
-+                                                   unsigned int state)
-+{
-+      struct arm_smccc_res res;
-+
-+      arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_FREQ_DYN_ADJ,
-+                           0, state, 0, 0, 0, 0, &res);
-+
-+      /* SMC signal correct apply by unsetting BIT 0 */
-+      return res.a0 & BIT(0) ? -EINVAL : 0;
-+}
-+
-+static int airoha_cpu_pmdomain_probe(struct platform_device *pdev)
-+{
-+      struct airoha_cpu_pmdomain_priv *priv;
-+      struct device *dev = &pdev->dev;
-+      struct clk_init_data init = { };
-+      struct generic_pm_domain *pd;
-+      struct clk_hw *hw;
-+      int ret;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      /* Init and register a get-only clk for Cpufreq */
-+      init.name = "cpu";
-+      init.ops = &airoha_cpu_pmdomain_clk_ops;
-+      /* Clock with no set_rate, can't cache */
-+      init.flags = CLK_GET_RATE_NOCACHE;
-+
-+      hw = &priv->hw;
-+      hw->init = &init;
-+      ret = devm_clk_hw_register(dev, hw);
-+      if (ret)
-+              return ret;
-+
-+      ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
-+      if (ret)
-+              return ret;
-+
-+      /* Init and register a PD for CPU */
-+      pd = &priv->pd;
-+      pd->name = "cpu_pd";
-+      pd->flags = GENPD_FLAG_ALWAYS_ON;
-+      pd->set_performance_state = airoha_cpu_pmdomain_set_performance_state;
-+
-+      ret = pm_genpd_init(pd, NULL, false);
-+      if (ret)
-+              return ret;
-+
-+      ret = of_genpd_add_provider_simple(dev->of_node, pd);
-+      if (ret)
-+              goto err_add_provider;
-+
-+      platform_set_drvdata(pdev, priv);
-+
-+      return 0;
-+
-+err_add_provider:
-+      pm_genpd_remove(pd);
-+
-+      return ret;
-+}
-+
-+static void airoha_cpu_pmdomain_remove(struct platform_device *pdev)
-+{
-+      struct airoha_cpu_pmdomain_priv *priv = platform_get_drvdata(pdev);
-+
-+      of_genpd_del_provider(pdev->dev.of_node);
-+      pm_genpd_remove(&priv->pd);
-+}
-+
-+static const struct of_device_id airoha_cpu_pmdomain_of_match[] = {
-+      { .compatible = "airoha,en7581-cpufreq" },
-+      { },
-+};
-+MODULE_DEVICE_TABLE(of, airoha_cpu_pmdomain_of_match);
-+
-+static struct platform_driver airoha_cpu_pmdomain_driver = {
-+      .probe = airoha_cpu_pmdomain_probe,
-+      .remove_new = airoha_cpu_pmdomain_remove,
-+      .driver = {
-+              .name = "airoha-cpu-pmdomain",
-+              .of_match_table = airoha_cpu_pmdomain_of_match,
-+      },
-+};
-+module_platform_driver(airoha_cpu_pmdomain_driver);
-+
-+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
-+MODULE_DESCRIPTION("CPU PM domain driver for Airoha SoCs");
-+MODULE_LICENSE("GPL");
diff --git a/target/linux/airoha/patches-6.6/100-02-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch b/target/linux/airoha/patches-6.6/100-02-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch
deleted file mode 100644 (file)
index 6a2e54f..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-From fa27cb99b297a1a9c0a5824afe5a670e424fff61 Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth@gmail.com>
-Date: Wed, 16 Oct 2024 18:00:57 +0200
-Subject: [PATCH v9 2/2] cpufreq: airoha: Add EN7581 CPUFreq SMCCC driver
-
-Add simple CPU Freq driver for Airoha EN7581 SoC that control CPU
-frequency scaling with SMC APIs and register a generic "cpufreq-dt"
-device.
-
-All CPU share the same frequency and can't be controlled independently.
-CPU frequency is controlled by the attached PM domain.
-
-Add SoC compatible to cpufreq-dt-plat block list as a dedicated cpufreq
-driver is needed with OPP v2 nodes declared in DTS.
-
-Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
----
-Changes v9:
-- Fix compile error targetting wrong branch (remove_new change and new PM OPs)
-Changes v8:
-- Split in dedicated PM domain driver
-Changes v7:
-- No changes
-Changes v6:
-- Improve Kconfig depends logic
-- Select PM (PM_GENERIC_DOMAINS depends on it)
-- Drop (int) cast for 
-Changes v5:
-- Rename cpu_pd to perf for power domain name
-- Use remove instead of remove_new
-Changes v4:
-- Rework to clk-only + PM set_performance_state implementation
-Changes v3:
-- Adapt to new cpufreq-dt APIs
-- Register cpufreq-dt instead of custom freq driver
-Changes v2:
-- Fix kernel bot error with missing slab.h and bitfield.h header
-- Limit COMPILE_TEST to ARM64 due to smcc 1.2
-
- drivers/cpufreq/Kconfig.arm          |   8 ++
- drivers/cpufreq/Makefile             |   1 +
- drivers/cpufreq/airoha-cpufreq.c     | 152 +++++++++++++++++++++++++++
- drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
- 4 files changed, 163 insertions(+)
- create mode 100644 drivers/cpufreq/airoha-cpufreq.c
-
---- a/drivers/cpufreq/Kconfig.arm
-+++ b/drivers/cpufreq/Kconfig.arm
-@@ -41,6 +41,14 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVME
-         To compile this driver as a module, choose M here: the
-         module will be called sun50i-cpufreq-nvmem.
-+config ARM_AIROHA_SOC_CPUFREQ
-+      tristate "Airoha EN7581 SoC CPUFreq support"
-+      depends on ARCH_AIROHA || COMPILE_TEST
-+      select PM_OPP
-+      default ARCH_AIROHA
-+      help
-+        This adds the CPUFreq driver for Airoha EN7581 SoCs.
-+
- config ARM_APPLE_SOC_CPUFREQ
-       tristate "Apple Silicon SoC CPUFreq support"
-       depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)
---- a/drivers/cpufreq/Makefile
-+++ b/drivers/cpufreq/Makefile
-@@ -52,6 +52,7 @@ obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY)       +
- ##################################################################################
- # ARM SoC drivers
-+obj-$(CONFIG_ARM_AIROHA_SOC_CPUFREQ)  += airoha-cpufreq.o
- obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ)   += apple-soc-cpufreq.o
- obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
- obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ)   += armada-8k-cpufreq.o
---- /dev/null
-+++ b/drivers/cpufreq/airoha-cpufreq.c
-@@ -0,0 +1,166 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+#include <linux/bitfield.h>
-+#include <linux/cpufreq.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/slab.h>
-+
-+#include "cpufreq-dt.h"
-+
-+struct airoha_cpufreq_priv {
-+      int opp_token;
-+      struct device **virt_devs;
-+      struct platform_device *cpufreq_dt;
-+};
-+
-+static struct platform_device *cpufreq_pdev;
-+
-+/* NOP function to disable OPP from setting clock */
-+static int airoha_cpufreq_config_clks_nop(struct device *dev,
-+                                        struct opp_table *opp_table,
-+                                        struct dev_pm_opp *old_opp,
-+                                        struct dev_pm_opp *opp,
-+                                        void *data, bool scaling_down)
-+{
-+      return 0;
-+}
-+
-+static const char * const airoha_cpufreq_clk_names[] = { "cpu", NULL };
-+static const char * const airoha_cpufreq_genpd_names[] = { "cpu_pd", NULL };
-+
-+static int airoha_cpufreq_probe(struct platform_device *pdev)
-+{
-+      struct dev_pm_opp_config config = { };
-+      struct platform_device *cpufreq_dt;
-+      struct airoha_cpufreq_priv *priv;
-+      struct device *dev = &pdev->dev;
-+      struct device **virt_devs = NULL;
-+      struct device *cpu_dev;
-+      int ret;
-+
-+      /* CPUs refer to the same OPP table */
-+      cpu_dev = get_cpu_device(0);
-+      if (!cpu_dev)
-+              return -ENODEV;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      config.clk_names = airoha_cpufreq_clk_names;
-+      config.config_clks = airoha_cpufreq_config_clks_nop;
-+      config.genpd_names = airoha_cpufreq_genpd_names;
-+      config.virt_devs = &virt_devs;
-+
-+      priv->opp_token = dev_pm_opp_set_config(cpu_dev, &config);
-+      if (priv->opp_token < 0)
-+              return dev_err_probe(dev, priv->opp_token, "Failed to set OPP config\n");
-+
-+      /* Set Attached PM for OPP ACTIVE */
-+      if (virt_devs) {
-+              const char * const *name = airoha_cpufreq_genpd_names;
-+              int i, j;
-+
-+              for (i = 0; *name; i++, name++) {
-+                      ret = pm_runtime_resume_and_get(virt_devs[i]);
-+                      if (ret) {
-+                              dev_err(cpu_dev, "failed to resume %s: %d\n",
-+                                      *name, ret);
-+
-+                              /* Rollback previous PM runtime calls */
-+                              name = config.genpd_names;
-+                              for (j = 0; *name && j < i; j++, name++)
-+                                      pm_runtime_put(virt_devs[j]);
-+
-+                              goto err_register_cpufreq;
-+                      }
-+              }
-+              priv->virt_devs = virt_devs;
-+      }
-+
-+      cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
-+      ret = PTR_ERR_OR_ZERO(cpufreq_dt);
-+      if (ret) {
-+              dev_err(dev, "failed to create cpufreq-dt device: %d\n", ret);
-+              goto err_register_cpufreq;
-+      }
-+
-+      priv->cpufreq_dt = cpufreq_dt;
-+      platform_set_drvdata(pdev, priv);
-+
-+      return 0;
-+
-+err_register_cpufreq:
-+      dev_pm_opp_clear_config(priv->opp_token);
-+
-+      return ret;
-+}
-+
-+static void airoha_cpufreq_remove(struct platform_device *pdev)
-+{
-+      struct airoha_cpufreq_priv *priv = platform_get_drvdata(pdev);
-+      const char * const *name = airoha_cpufreq_genpd_names;
-+      int i;
-+
-+      platform_device_unregister(priv->cpufreq_dt);
-+
-+      dev_pm_opp_clear_config(priv->opp_token);
-+
-+      for (i = 0; *name; i++, name++)
-+              pm_runtime_put(priv->virt_devs[i]);
-+}
-+
-+static struct platform_driver airoha_cpufreq_driver = {
-+      .probe = airoha_cpufreq_probe,
-+      .remove_new = airoha_cpufreq_remove,
-+      .driver = {
-+              .name = "airoha-cpufreq",
-+      },
-+};
-+
-+static const struct of_device_id airoha_cpufreq_match_list[] __initconst = {
-+      { .compatible = "airoha,en7581" },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, airoha_cpufreq_match_list);
-+
-+static int __init airoha_cpufreq_init(void)
-+{
-+      struct device_node *np = of_find_node_by_path("/");
-+      const struct of_device_id *match;
-+      int ret;
-+
-+      if (!np)
-+              return -ENODEV;
-+
-+      match = of_match_node(airoha_cpufreq_match_list, np);
-+      of_node_put(np);
-+      if (!match)
-+              return -ENODEV;
-+
-+      ret = platform_driver_register(&airoha_cpufreq_driver);
-+      if (unlikely(ret < 0))
-+              return ret;
-+
-+      cpufreq_pdev = platform_device_register_data(NULL, "airoha-cpufreq",
-+                                                   -1, match, sizeof(*match));
-+      ret = PTR_ERR_OR_ZERO(cpufreq_pdev);
-+      if (ret)
-+              platform_driver_unregister(&airoha_cpufreq_driver);
-+
-+      return ret;
-+}
-+module_init(airoha_cpufreq_init);
-+
-+static void __exit airoha_cpufreq_exit(void)
-+{
-+      platform_device_unregister(cpufreq_pdev);
-+      platform_driver_unregister(&airoha_cpufreq_driver);
-+}
-+module_exit(airoha_cpufreq_exit);
-+
-+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
-+MODULE_DESCRIPTION("CPUfreq driver for Airoha SoCs");
-+MODULE_LICENSE("GPL");
---- a/drivers/cpufreq/cpufreq-dt-platdev.c
-+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
-@@ -103,6 +103,8 @@ static const struct of_device_id allowli
-  * platforms using "operating-points-v2" property.
-  */
- static const struct of_device_id blocklist[] __initconst = {
-+      { .compatible = "airoha,en7581", },
-+
-       { .compatible = "allwinner,sun50i-h6", },
-       { .compatible = "apple,arm-platform", },