mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-27 14:49:55 +00:00
airoha: an7581: replace cpufreq patch with new version
Replace cpufreq patch with new version requested upstream. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> (cherry picked from commit 506955735075241d3467d632cae7ed5f10e21c2f)
This commit is contained in:
parent
9a18304344
commit
90c29d2c04
@ -0,0 +1,201 @@
|
||||
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");
|
@ -0,0 +1,253 @@
|
||||
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", },
|
@ -1,247 +0,0 @@
|
||||
From 5296da64f77ef6c809b715cdecf308977a08acb9 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@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@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@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", },
|
Loading…
x
Reference in New Issue
Block a user