[openwrt/openwrt] airoha: an7581: replace cpufreq patch with new version

LEDE Commits lede-commits at lists.infradead.org
Fri Jan 10 05:58:19 PST 2025


ansuel pushed a commit to openwrt/openwrt.git, branch openwrt-24.10:
https://git.openwrt.org/90c29d2c04407f3269c299eaa239c3be283981c9

commit 90c29d2c04407f3269c299eaa239c3be283981c9
Author: Christian Marangi <ansuelsmth at gmail.com>
AuthorDate: Fri Jan 10 14:53:04 2025 +0100

    airoha: an7581: replace cpufreq patch with new version
    
    Replace cpufreq patch with new version requested upstream.
    
    Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
    (cherry picked from commit 506955735075241d3467d632cae7ed5f10e21c2f)
---
 ...n-airoha-Add-Airoha-CPU-PM-Domain-support.patch | 201 ++++++++++++++++
 ...eq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch | 253 +++++++++++++++++++++
 ...freq-airoha-Add-EN7581-Cpufreq-SMC-driver.patch | 247 --------------------
 3 files changed, 454 insertions(+), 247 deletions(-)

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
new file mode 100644
index 0000000000..52d3f40b36
--- /dev/null
+++ b/target/linux/airoha/patches-6.6/100-01-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch
@@ -0,0 +1,201 @@
+From 76e4e6ce9aaae897f80e375345bf0095e1b09ff2 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at 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 at 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 at 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
new file mode 100644
index 0000000000..6a2e54f4d1
--- /dev/null
+++ b/target/linux/airoha/patches-6.6/100-02-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch
@@ -0,0 +1,253 @@
+From fa27cb99b297a1a9c0a5824afe5a670e424fff61 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at 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 at 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 at 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/100-cpufreq-airoha-Add-EN7581-Cpufreq-SMC-driver.patch b/target/linux/airoha/patches-6.6/100-cpufreq-airoha-Add-EN7581-Cpufreq-SMC-driver.patch
deleted file mode 100644
index 0276a4ee81..0000000000
--- a/target/linux/airoha/patches-6.6/100-cpufreq-airoha-Add-EN7581-Cpufreq-SMC-driver.patch
+++ /dev/null
@@ -1,247 +0,0 @@
-From 5296da64f77ef6c809b715cdecf308977a08acb9 Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth at gmail.com>
-Date: Wed, 16 Oct 2024 18:00:57 +0200
-Subject: [PATCH] cpufreq: airoha: Add EN7581 Cpufreq SMC driver
-
-Add simple Cpufreq driver for Airoha EN7581 SoC that control CPU
-frequency scaling with SMC APIs.
-
-All CPU share the same frequency and can't be controlled independently.
-Current shared CPU frequency is returned by the related SMC command.
-
-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 at gmail.com>
----
- drivers/cpufreq/Kconfig.arm          |   8 ++
- drivers/cpufreq/Makefile             |   1 +
- drivers/cpufreq/airoha-cpufreq.c     | 183 +++++++++++++++++++++++++++
- drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
- 4 files changed, 194 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,183 @@
-+// SPDX-License-Identifier: GPL-2.0
-+
-+#include <linux/cpufreq.h>
-+#include <linux/module.h>
-+#include <linux/arm-smccc.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_cpufreq_priv {
-+	struct list_head list;
-+
-+	cpumask_var_t cpus;
-+	struct device *cpu_dev;
-+	struct cpufreq_frequency_table *freq_table;
-+};
-+
-+static LIST_HEAD(priv_list);
-+
-+static unsigned int airoha_cpufreq_get(unsigned int cpu)
-+{
-+	const struct arm_smccc_1_2_regs args = {
-+		.a0 = AIROHA_SIP_AVS_HANDLE,
-+		.a1 = AIROHA_AVS_OP_GET_FREQ,
-+	};
-+	struct arm_smccc_1_2_regs res;
-+
-+	arm_smccc_1_2_smc(&args, &res);
-+
-+	return (int)(res.a0 * 1000);
-+}
-+
-+static int airoha_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
-+{
-+	const struct arm_smccc_1_2_regs args = {
-+		.a0 = AIROHA_SIP_AVS_HANDLE,
-+		.a1 = AIROHA_AVS_OP_FREQ_DYN_ADJ,
-+		.a3 = index,
-+	};
-+	struct arm_smccc_1_2_regs res;
-+
-+	arm_smccc_1_2_smc(&args, &res);
-+
-+	/* SMC signal correct apply by unsetting BIT 0 */
-+	return res.a0 & BIT(0) ? -EINVAL : 0;
-+}
-+
-+static struct airoha_cpufreq_priv *airoha_cpufreq_find_data(int cpu)
-+{
-+	struct airoha_cpufreq_priv *priv;
-+
-+	list_for_each_entry(priv, &priv_list, list) {
-+		if (cpumask_test_cpu(cpu, priv->cpus))
-+			return priv;
-+	}
-+
-+	return NULL;
-+}
-+
-+static int airoha_cpufreq_init(struct cpufreq_policy *policy)
-+{
-+	struct airoha_cpufreq_priv *priv;
-+	struct device *cpu_dev;
-+
-+	priv = airoha_cpufreq_find_data(policy->cpu);
-+	if (!priv)
-+		return -ENODEV;
-+
-+	cpu_dev = priv->cpu_dev;
-+	cpumask_copy(policy->cpus, priv->cpus);
-+	policy->driver_data = priv;
-+	policy->freq_table = priv->freq_table;
-+
-+	return 0;
-+}
-+
-+static struct cpufreq_driver airoha_cpufreq_driver = {
-+	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK |
-+			  CPUFREQ_IS_COOLING_DEV,
-+	.verify		= cpufreq_generic_frequency_table_verify,
-+	.target_index	= airoha_cpufreq_set_target,
-+	.get		= airoha_cpufreq_get,
-+	.init		= airoha_cpufreq_init,
-+	.attr		= cpufreq_generic_attr,
-+	.name		= "airoha-cpufreq",
-+};
-+
-+static int airoha_cpufreq_driver_init_cpu(int cpu)
-+{
-+	struct airoha_cpufreq_priv *priv;
-+	struct device *cpu_dev;
-+	int ret;
-+
-+	cpu_dev = get_cpu_device(cpu);
-+	if (!cpu_dev)
-+		return -EPROBE_DEFER;
-+
-+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+	if (!priv)
-+		return -ENOMEM;
-+
-+	if (!zalloc_cpumask_var(&priv->cpus, GFP_KERNEL))
-+		return -ENOMEM;
-+
-+	cpumask_set_cpu(cpu, priv->cpus);
-+	priv->cpu_dev = cpu_dev;
-+
-+	ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, priv->cpus);
-+	if (ret)
-+		goto err;
-+
-+	ret = dev_pm_opp_of_cpumask_add_table(priv->cpus);
-+	if (ret)
-+		goto err;
-+
-+	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &priv->freq_table);
-+	if (ret)
-+		goto err;
-+
-+	list_add(&priv->list, &priv_list);
-+
-+	return 0;
-+
-+err:
-+	dev_pm_opp_of_cpumask_remove_table(priv->cpus);
-+	free_cpumask_var(priv->cpus);
-+
-+	return ret;
-+}
-+
-+static void airoha_cpufreq_release(void)
-+{
-+	struct airoha_cpufreq_priv *priv, *tmp;
-+
-+	list_for_each_entry_safe(priv, tmp, &priv_list, list) {
-+		dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &priv->freq_table);
-+		dev_pm_opp_of_cpumask_remove_table(priv->cpus);
-+		free_cpumask_var(priv->cpus);
-+		list_del(&priv->list);
-+		kfree(priv);
-+	}
-+}
-+
-+static int __init airoha_cpufreq_driver_probe(void)
-+{
-+	int cpu, ret;
-+
-+	if (!of_machine_is_compatible("airoha,en7581"))
-+		return -ENODEV;
-+
-+	for_each_possible_cpu(cpu) {
-+		ret = airoha_cpufreq_driver_init_cpu(cpu);
-+		if (ret)
-+			goto err;
-+	}
-+
-+	ret = cpufreq_register_driver(&airoha_cpufreq_driver);
-+	if (ret)
-+		goto err;
-+
-+	return 0;
-+
-+err:
-+	airoha_cpufreq_release();
-+	return ret;
-+}
-+module_init(airoha_cpufreq_driver_probe);
-+
-+static void __exit airoha_cpufreq_driver_remove(void)
-+{
-+	cpufreq_unregister_driver(&airoha_cpufreq_driver);
-+	airoha_cpufreq_release();
-+}
-+module_exit(airoha_cpufreq_driver_remove);
-+
-+MODULE_AUTHOR("Christian Marangi <ansuelsmth at 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", },




More information about the lede-commits mailing list