From: Christian Marangi Date: Mon, 27 Jan 2025 10:07:13 +0000 (+0100) Subject: airoha: an7581: refresh and fix cpufreq patch X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=fbbfcbf150cd7c72f49c149e7f9b9f4d0bf43e4b;p=openwrt%2Fstaging%2Fnbd.git airoha: an7581: refresh and fix cpufreq patch 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 --- diff --git a/target/linux/airoha/an7581/config-6.6 b/target/linux/airoha/an7581/config-6.6 index f80bf49f8c..d86aa8bbbb 100644 --- a/target/linux/airoha/an7581/config-6.6 +++ b/target/linux/airoha/an7581/config-6.6 @@ -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 diff --git a/target/linux/airoha/dts/an7581.dtsi b/target/linux/airoha/dts/an7581.dtsi index 820ab0bfa8..2b4c1b716b 100644 --- a/target/linux/airoha/dts/an7581.dtsi +++ b/target/linux/airoha/dts/an7581.dtsi @@ -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>; }; @@ -109,7 +109,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>; }; @@ -123,7 +123,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>; }; 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 index 0000000000..0db82d55e1 --- /dev/null +++ b/target/linux/airoha/patches-6.6/039-v6.14-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch @@ -0,0 +1,232 @@ +From 84cf9e541cccb8cb698518a9897942e8c78f1d83 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +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 +Signed-off-by: Viresh Kumar +--- + 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 ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++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 index 0000000000..8dc8a3d304 --- /dev/null +++ b/target/linux/airoha/patches-6.6/040-v6.14-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch @@ -0,0 +1,196 @@ +From 82e703dd438b71432cc0ccbb90925d1e32dd014a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +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 +Link: https://lore.kernel.org/r/20250109131313.32317-1-ansuelsmth@gmail.com +Signed-off-by: Ulf Hansson +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++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 index 52d3f40b36..0000000000 --- a/target/linux/airoha/patches-6.6/100-01-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch +++ /dev/null @@ -1,201 +0,0 @@ -From 76e4e6ce9aaae897f80e375345bf0095e1b09ff2 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -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 ---- -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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 "); -+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 index 6a2e54f4d1..0000000000 --- a/target/linux/airoha/patches-6.6/100-02-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch +++ /dev/null @@ -1,253 +0,0 @@ -From fa27cb99b297a1a9c0a5824afe5a670e424fff61 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -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 ---- -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 -+#include -+#include -+#include -+#include -+#include -+ -+#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 "); -+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", },