mirror of
				https://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 15:56:03 +00:00 
			
		
		
		
	Refresh patches 6.12 for airoha and econet Fixes:122135b964("airoha: an7581: add support for kernel 6.12") Fixes:73d0f92460("kernel: Add new platform EcoNet MIPS") Signed-off-by: Leo Barsky <leobrsky@proton.me> Link: https://github.com/openwrt/openwrt/pull/20073 Signed-off-by: Robert Marko <robimarko@gmail.com>
		
			
				
	
	
		
			233 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			233 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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
 | |
| @@ -15,6 +15,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 = "allwinner,sun50i-h616", },
 | |
|  	{ .compatible = "allwinner,sun50i-h618", },
 |