Skip to content

Commit a5c16f2

Browse files
committed
Merge branch 'pm-cpufreq'
Merge cpufreq updates for 6.14: - Use str_enable_disable()-like helpers in cpufreq (Krzysztof Kozlowski). - Extend the Apple cpufreq driver to support more SoCs (Hector Martin, Nick Chan). - Add new cpufreq driver for Airoha SoCs (Christian Marangi). - Fix using cpufreq-dt as module (Andreas Kemnade). - Minor fixes for Sparc, SCMI, and Qcom cpufreq drivers (Ethan Carter Edwards, Sibi Sankar, Manivannan Sadhasivam). - Fix the maximum supported frequency computation in the ACPI cpufreq driver to avoid relying on unfounded assumptions (Gautham Shenoy). - Fix an amd-pstate driver regression with preferred core rankings not being used (Mario Limonciello). - Fix a precision issue with frequency calculation in the amd-pstate driver (Naresh Solanki). - Add ftrace event to the amd-pstate driver for active mode (Mario Limonciello). - Set default EPP policy on Ryzen processors in amd-pstate (Mario Limonciello). - Clean up the amd-pstate cpufreq driver and optimize it to increase code reuse (Mario Limonciello, Dhananjay Ugwekar). - Use CPPC to get scaling factors between HWP performance levels and frequency in the intel_pstate driver and make it stop using a built -in scaling factor for the Arrow Lake processor (Rafael Wysocki). - Make intel_pstate initialize epp_policy to CPUFREQ_POLICY_UNKNOWN for consistency with CPU offline (Christian Loehle). - Fix superfluous updates caused by need_freq_update in the schedutil cpufreq governor (Sultan Alsawaf). * pm-cpufreq: (40 commits) cpufreq: Use str_enable_disable()-like helpers cpufreq: airoha: Add EN7581 CPUFreq SMCCC driver cpufreq: ACPI: Fix max-frequency computation cpufreq/amd-pstate: Refactor max frequency calculation cpufreq/amd-pstate: Fix prefcore rankings cpufreq: sparc: change kzalloc to kcalloc cpufreq: qcom: Implement clk_ops::determine_rate() for qcom_cpufreq* clocks cpufreq: qcom: Fix qcom_cpufreq_hw_recalc_rate() to query LUT if LMh IRQ is not available cpufreq: apple-soc: Add Apple A7-A8X SoC cpufreq support cpufreq: apple-soc: Set fallback transition latency to APPLE_DVFS_TRANSITION_TIMEOUT cpufreq: apple-soc: Increase cluster switch timeout to 400us cpufreq: apple-soc: Use 32-bit read for status register cpufreq: apple-soc: Allow per-SoC configuration of APPLE_DVFS_CMD_PS1 cpufreq: apple-soc: Drop setting the PS2 field on M2+ dt-bindings: cpufreq: apple,cluster-cpufreq: Add A7-A11, T2 compatibles dt-bindings: cpufreq: Document support for Airoha EN7581 CPUFreq cpufreq: fix using cpufreq-dt as module cpufreq: scmi: Register for limit change notifications cpufreq: schedutil: Fix superfluous updates caused by need_freq_update cpufreq: intel_pstate: Use CPUFREQ_POLICY_UNKNOWN ...
2 parents 1225bb4 + 251be0b commit a5c16f2

21 files changed

+691
-340
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/cpufreq/airoha,en7581-cpufreq.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Airoha EN7581 CPUFreq
8+
9+
maintainers:
10+
- Christian Marangi <ansuelsmth@gmail.com>
11+
12+
description: |
13+
On newer Airoha SoC, CPU Frequency is scaled indirectly with SMC commands
14+
to ATF.
15+
16+
A virtual clock is exposed. This virtual clock is a get-only clock and
17+
is used to expose the current global CPU clock. The frequency info comes
18+
by the output of the SMC command that reports the clock in MHz.
19+
20+
The SMC sets the CPU clock by providing an index, this is modelled as
21+
performance states in a power domain.
22+
23+
CPUs can't be individually scaled as the CPU frequency is shared across
24+
all CPUs and is global.
25+
26+
properties:
27+
compatible:
28+
const: airoha,en7581-cpufreq
29+
30+
'#clock-cells':
31+
const: 0
32+
33+
'#power-domain-cells':
34+
const: 0
35+
36+
operating-points-v2: true
37+
38+
required:
39+
- compatible
40+
- '#clock-cells'
41+
- '#power-domain-cells'
42+
- operating-points-v2
43+
44+
additionalProperties: false
45+
46+
examples:
47+
- |
48+
performance-domain {
49+
compatible = "airoha,en7581-cpufreq";
50+
51+
operating-points-v2 = <&cpu_smcc_opp_table>;
52+
53+
#power-domain-cells = <0>;
54+
#clock-cells = <0>;
55+
};

Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,17 @@ properties:
2424
- apple,t8112-cluster-cpufreq
2525
- const: apple,cluster-cpufreq
2626
- items:
27-
- const: apple,t6000-cluster-cpufreq
27+
- enum:
28+
- apple,s8000-cluster-cpufreq
29+
- apple,t8010-cluster-cpufreq
30+
- apple,t8015-cluster-cpufreq
31+
- apple,t6000-cluster-cpufreq
2832
- const: apple,t8103-cluster-cpufreq
2933
- const: apple,cluster-cpufreq
34+
- items:
35+
- const: apple,t7000-cluster-cpufreq
36+
- const: apple,s5l8960x-cluster-cpufreq
37+
- const: apple,s5l8960x-cluster-cpufreq
3038

3139
reg:
3240
maxItems: 1

drivers/cpufreq/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ config CPUFREQ_VIRT
232232
If in doubt, say N.
233233

234234
config CPUFREQ_DT_PLATDEV
235-
tristate "Generic DT based cpufreq platdev driver"
235+
bool "Generic DT based cpufreq platdev driver"
236236
depends on OF
237237
help
238238
This adds a generic DT based cpufreq platdev driver for frequency

drivers/cpufreq/Kconfig.arm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
1515
To compile this driver as a module, choose M here: the
1616
module will be called sun50i-cpufreq-nvmem.
1717

18+
config ARM_AIROHA_SOC_CPUFREQ
19+
tristate "Airoha EN7581 SoC CPUFreq support"
20+
depends on ARCH_AIROHA || COMPILE_TEST
21+
select PM_OPP
22+
default ARCH_AIROHA
23+
help
24+
This adds the CPUFreq driver for Airoha EN7581 SoCs.
25+
1826
config ARM_APPLE_SOC_CPUFREQ
1927
tristate "Apple Silicon SoC CPUFreq support"
2028
depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)

drivers/cpufreq/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o
5353

5454
##################################################################################
5555
# ARM SoC drivers
56+
obj-$(CONFIG_ARM_AIROHA_SOC_CPUFREQ) += airoha-cpufreq.o
5657
obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ) += apple-soc-cpufreq.o
5758
obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
5859
obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ) += armada-8k-cpufreq.o

drivers/cpufreq/acpi-cpufreq.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,14 @@ static int acpi_cpufreq_blacklist(struct cpuinfo_x86 *c)
623623
#endif
624624

625625
#ifdef CONFIG_ACPI_CPPC_LIB
626-
static u64 get_max_boost_ratio(unsigned int cpu)
626+
/*
627+
* get_max_boost_ratio: Computes the max_boost_ratio as the ratio
628+
* between the highest_perf and the nominal_perf.
629+
*
630+
* Returns the max_boost_ratio for @cpu. Returns the CPPC nominal
631+
* frequency via @nominal_freq if it is non-NULL pointer.
632+
*/
633+
static u64 get_max_boost_ratio(unsigned int cpu, u64 *nominal_freq)
627634
{
628635
struct cppc_perf_caps perf_caps;
629636
u64 highest_perf, nominal_perf;
@@ -652,6 +659,9 @@ static u64 get_max_boost_ratio(unsigned int cpu)
652659

653660
nominal_perf = perf_caps.nominal_perf;
654661

662+
if (nominal_freq)
663+
*nominal_freq = perf_caps.nominal_freq;
664+
655665
if (!highest_perf || !nominal_perf) {
656666
pr_debug("CPU%d: highest or nominal performance missing\n", cpu);
657667
return 0;
@@ -664,8 +674,12 @@ static u64 get_max_boost_ratio(unsigned int cpu)
664674

665675
return div_u64(highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
666676
}
677+
667678
#else
668-
static inline u64 get_max_boost_ratio(unsigned int cpu) { return 0; }
679+
static inline u64 get_max_boost_ratio(unsigned int cpu, u64 *nominal_freq)
680+
{
681+
return 0;
682+
}
669683
#endif
670684

671685
static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
@@ -675,9 +689,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
675689
struct acpi_cpufreq_data *data;
676690
unsigned int cpu = policy->cpu;
677691
struct cpuinfo_x86 *c = &cpu_data(cpu);
692+
u64 max_boost_ratio, nominal_freq = 0;
678693
unsigned int valid_states = 0;
679694
unsigned int result = 0;
680-
u64 max_boost_ratio;
681695
unsigned int i;
682696
#ifdef CONFIG_SMP
683697
static int blacklisted;
@@ -827,16 +841,20 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
827841
}
828842
freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
829843

830-
max_boost_ratio = get_max_boost_ratio(cpu);
844+
max_boost_ratio = get_max_boost_ratio(cpu, &nominal_freq);
831845
if (max_boost_ratio) {
832-
unsigned int freq = freq_table[0].frequency;
846+
unsigned int freq = nominal_freq;
833847

834848
/*
835-
* Because the loop above sorts the freq_table entries in the
836-
* descending order, freq is the maximum frequency in the table.
837-
* Assume that it corresponds to the CPPC nominal frequency and
838-
* use it to set cpuinfo.max_freq.
849+
* The loop above sorts the freq_table entries in the
850+
* descending order. If ACPI CPPC has not advertised
851+
* the nominal frequency (this is possible in CPPC
852+
* revisions prior to 3), then use the first entry in
853+
* the pstate table as a proxy for nominal frequency.
839854
*/
855+
if (!freq)
856+
freq = freq_table[0].frequency;
857+
840858
policy->cpuinfo.max_freq = freq * max_boost_ratio >> SCHED_CAPACITY_SHIFT;
841859
} else {
842860
/*

drivers/cpufreq/airoha-cpufreq.c

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/bitfield.h>
4+
#include <linux/cpufreq.h>
5+
#include <linux/module.h>
6+
#include <linux/platform_device.h>
7+
#include <linux/pm_domain.h>
8+
#include <linux/pm_runtime.h>
9+
#include <linux/slab.h>
10+
11+
#include "cpufreq-dt.h"
12+
13+
struct airoha_cpufreq_priv {
14+
int opp_token;
15+
struct dev_pm_domain_list *pd_list;
16+
struct platform_device *cpufreq_dt;
17+
};
18+
19+
static struct platform_device *cpufreq_pdev;
20+
21+
/* NOP function to disable OPP from setting clock */
22+
static int airoha_cpufreq_config_clks_nop(struct device *dev,
23+
struct opp_table *opp_table,
24+
struct dev_pm_opp *opp,
25+
void *data, bool scaling_down)
26+
{
27+
return 0;
28+
}
29+
30+
static const char * const airoha_cpufreq_clk_names[] = { "cpu", NULL };
31+
static const char * const airoha_cpufreq_pd_names[] = { "perf" };
32+
33+
static int airoha_cpufreq_probe(struct platform_device *pdev)
34+
{
35+
const struct dev_pm_domain_attach_data attach_data = {
36+
.pd_names = airoha_cpufreq_pd_names,
37+
.num_pd_names = ARRAY_SIZE(airoha_cpufreq_pd_names),
38+
.pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP,
39+
};
40+
struct dev_pm_opp_config config = {
41+
.clk_names = airoha_cpufreq_clk_names,
42+
.config_clks = airoha_cpufreq_config_clks_nop,
43+
};
44+
struct platform_device *cpufreq_dt;
45+
struct airoha_cpufreq_priv *priv;
46+
struct device *dev = &pdev->dev;
47+
struct device *cpu_dev;
48+
int ret;
49+
50+
/* CPUs refer to the same OPP table */
51+
cpu_dev = get_cpu_device(0);
52+
if (!cpu_dev)
53+
return -ENODEV;
54+
55+
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
56+
if (!priv)
57+
return -ENOMEM;
58+
59+
/* Set OPP table conf with NOP config_clks */
60+
priv->opp_token = dev_pm_opp_set_config(cpu_dev, &config);
61+
if (priv->opp_token < 0)
62+
return dev_err_probe(dev, priv->opp_token, "Failed to set OPP config\n");
63+
64+
/* Attach PM for OPP */
65+
ret = dev_pm_domain_attach_list(cpu_dev, &attach_data,
66+
&priv->pd_list);
67+
if (ret)
68+
goto clear_opp_config;
69+
70+
cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
71+
ret = PTR_ERR_OR_ZERO(cpufreq_dt);
72+
if (ret) {
73+
dev_err(dev, "failed to create cpufreq-dt device: %d\n", ret);
74+
goto detach_pm;
75+
}
76+
77+
priv->cpufreq_dt = cpufreq_dt;
78+
platform_set_drvdata(pdev, priv);
79+
80+
return 0;
81+
82+
detach_pm:
83+
dev_pm_domain_detach_list(priv->pd_list);
84+
clear_opp_config:
85+
dev_pm_opp_clear_config(priv->opp_token);
86+
87+
return ret;
88+
}
89+
90+
static void airoha_cpufreq_remove(struct platform_device *pdev)
91+
{
92+
struct airoha_cpufreq_priv *priv = platform_get_drvdata(pdev);
93+
94+
platform_device_unregister(priv->cpufreq_dt);
95+
96+
dev_pm_domain_detach_list(priv->pd_list);
97+
98+
dev_pm_opp_clear_config(priv->opp_token);
99+
}
100+
101+
static struct platform_driver airoha_cpufreq_driver = {
102+
.probe = airoha_cpufreq_probe,
103+
.remove = airoha_cpufreq_remove,
104+
.driver = {
105+
.name = "airoha-cpufreq",
106+
},
107+
};
108+
109+
static const struct of_device_id airoha_cpufreq_match_list[] __initconst = {
110+
{ .compatible = "airoha,en7581" },
111+
{},
112+
};
113+
MODULE_DEVICE_TABLE(of, airoha_cpufreq_match_list);
114+
115+
static int __init airoha_cpufreq_init(void)
116+
{
117+
struct device_node *np = of_find_node_by_path("/");
118+
const struct of_device_id *match;
119+
int ret;
120+
121+
if (!np)
122+
return -ENODEV;
123+
124+
match = of_match_node(airoha_cpufreq_match_list, np);
125+
of_node_put(np);
126+
if (!match)
127+
return -ENODEV;
128+
129+
ret = platform_driver_register(&airoha_cpufreq_driver);
130+
if (unlikely(ret < 0))
131+
return ret;
132+
133+
cpufreq_pdev = platform_device_register_data(NULL, "airoha-cpufreq",
134+
-1, match, sizeof(*match));
135+
ret = PTR_ERR_OR_ZERO(cpufreq_pdev);
136+
if (ret)
137+
platform_driver_unregister(&airoha_cpufreq_driver);
138+
139+
return ret;
140+
}
141+
module_init(airoha_cpufreq_init);
142+
143+
static void __exit airoha_cpufreq_exit(void)
144+
{
145+
platform_device_unregister(cpufreq_pdev);
146+
platform_driver_unregister(&airoha_cpufreq_driver);
147+
}
148+
module_exit(airoha_cpufreq_exit);
149+
150+
MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
151+
MODULE_DESCRIPTION("CPUfreq driver for Airoha SoCs");
152+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)