Skip to content

Commit 251be0b

Browse files
committed
Merge tag 'cpufreq-arm-updates-6.14' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/vireshk/pm
Merge ARM cpufreq updates for 6.14 from Viresh Kumar: "- Extended support for more SoCs in apple cpufreq driver (Hector Martin and 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 drivers (Ethan Carter Edwards, Sibi Sankar and Manivannan Sadhasivam)." * tag 'cpufreq-arm-updates-6.14' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/vireshk/pm: cpufreq: airoha: Add EN7581 CPUFreq SMCCC driver 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
2 parents f994c1c + 84cf9e5 commit 251be0b

File tree

12 files changed

+344
-27
lines changed

12 files changed

+344
-27
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/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");

drivers/cpufreq/apple-soc-cpufreq.c

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222
#include <linux/pm_opp.h>
2323
#include <linux/slab.h>
2424

25-
#define APPLE_DVFS_CMD 0x20
26-
#define APPLE_DVFS_CMD_BUSY BIT(31)
27-
#define APPLE_DVFS_CMD_SET BIT(25)
28-
#define APPLE_DVFS_CMD_PS2 GENMASK(16, 12)
29-
#define APPLE_DVFS_CMD_PS1 GENMASK(4, 0)
25+
#define APPLE_DVFS_CMD 0x20
26+
#define APPLE_DVFS_CMD_BUSY BIT(31)
27+
#define APPLE_DVFS_CMD_SET BIT(25)
28+
#define APPLE_DVFS_CMD_PS1_S5L8960X GENMASK(24, 22)
29+
#define APPLE_DVFS_CMD_PS1_S5L8960X_SHIFT 22
30+
#define APPLE_DVFS_CMD_PS2 GENMASK(15, 12)
31+
#define APPLE_DVFS_CMD_PS1 GENMASK(4, 0)
32+
#define APPLE_DVFS_CMD_PS1_SHIFT 0
3033

3134
/* Same timebase as CPU counter (24MHz) */
3235
#define APPLE_DVFS_LAST_CHG_TIME 0x38
@@ -35,6 +38,9 @@
3538
* Apple ran out of bits and had to shift this in T8112...
3639
*/
3740
#define APPLE_DVFS_STATUS 0x50
41+
#define APPLE_DVFS_STATUS_CUR_PS_S5L8960X GENMASK(5, 3)
42+
#define APPLE_DVFS_STATUS_CUR_PS_SHIFT_S5L8960X 3
43+
#define APPLE_DVFS_STATUS_TGT_PS_S5L8960X GENMASK(2, 0)
3844
#define APPLE_DVFS_STATUS_CUR_PS_T8103 GENMASK(7, 4)
3945
#define APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8103 4
4046
#define APPLE_DVFS_STATUS_TGT_PS_T8103 GENMASK(3, 0)
@@ -52,12 +58,15 @@
5258
#define APPLE_DVFS_PLL_FACTOR_MULT GENMASK(31, 16)
5359
#define APPLE_DVFS_PLL_FACTOR_DIV GENMASK(15, 0)
5460

55-
#define APPLE_DVFS_TRANSITION_TIMEOUT 100
61+
#define APPLE_DVFS_TRANSITION_TIMEOUT 400
5662

5763
struct apple_soc_cpufreq_info {
64+
bool has_ps2;
5865
u64 max_pstate;
5966
u64 cur_pstate_mask;
6067
u64 cur_pstate_shift;
68+
u64 ps1_mask;
69+
u64 ps1_shift;
6170
};
6271

6372
struct apple_cpu_priv {
@@ -68,24 +77,46 @@ struct apple_cpu_priv {
6877

6978
static struct cpufreq_driver apple_soc_cpufreq_driver;
7079

80+
static const struct apple_soc_cpufreq_info soc_s5l8960x_info = {
81+
.has_ps2 = false,
82+
.max_pstate = 7,
83+
.cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_S5L8960X,
84+
.cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_S5L8960X,
85+
.ps1_mask = APPLE_DVFS_CMD_PS1_S5L8960X,
86+
.ps1_shift = APPLE_DVFS_CMD_PS1_S5L8960X_SHIFT,
87+
};
88+
7189
static const struct apple_soc_cpufreq_info soc_t8103_info = {
90+
.has_ps2 = true,
7291
.max_pstate = 15,
7392
.cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_T8103,
7493
.cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8103,
94+
.ps1_mask = APPLE_DVFS_CMD_PS1,
95+
.ps1_shift = APPLE_DVFS_CMD_PS1_SHIFT,
7596
};
7697

7798
static const struct apple_soc_cpufreq_info soc_t8112_info = {
99+
.has_ps2 = false,
78100
.max_pstate = 31,
79101
.cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_T8112,
80102
.cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8112,
103+
.ps1_mask = APPLE_DVFS_CMD_PS1,
104+
.ps1_shift = APPLE_DVFS_CMD_PS1_SHIFT,
81105
};
82106

83107
static const struct apple_soc_cpufreq_info soc_default_info = {
108+
.has_ps2 = false,
84109
.max_pstate = 15,
85110
.cur_pstate_mask = 0, /* fallback */
111+
.ps1_mask = APPLE_DVFS_CMD_PS1,
112+
.ps1_shift = APPLE_DVFS_CMD_PS1_SHIFT,
86113
};
87114

88115
static const struct of_device_id apple_soc_cpufreq_of_match[] __maybe_unused = {
116+
{
117+
.compatible = "apple,s5l8960x-cluster-cpufreq",
118+
.data = &soc_s5l8960x_info,
119+
},
89120
{
90121
.compatible = "apple,t8103-cluster-cpufreq",
91122
.data = &soc_t8103_info,
@@ -109,7 +140,7 @@ static unsigned int apple_soc_cpufreq_get_rate(unsigned int cpu)
109140
unsigned int pstate;
110141

111142
if (priv->info->cur_pstate_mask) {
112-
u64 reg = readq_relaxed(priv->reg_base + APPLE_DVFS_STATUS);
143+
u32 reg = readl_relaxed(priv->reg_base + APPLE_DVFS_STATUS);
113144

114145
pstate = (reg & priv->info->cur_pstate_mask) >> priv->info->cur_pstate_shift;
115146
} else {
@@ -148,9 +179,12 @@ static int apple_soc_cpufreq_set_target(struct cpufreq_policy *policy,
148179
return -EIO;
149180
}
150181

151-
reg &= ~(APPLE_DVFS_CMD_PS1 | APPLE_DVFS_CMD_PS2);
152-
reg |= FIELD_PREP(APPLE_DVFS_CMD_PS1, pstate);
153-
reg |= FIELD_PREP(APPLE_DVFS_CMD_PS2, pstate);
182+
reg &= ~priv->info->ps1_mask;
183+
reg |= pstate << priv->info->ps1_shift;
184+
if (priv->info->has_ps2) {
185+
reg &= ~APPLE_DVFS_CMD_PS2;
186+
reg |= FIELD_PREP(APPLE_DVFS_CMD_PS2, pstate);
187+
}
154188
reg |= APPLE_DVFS_CMD_SET;
155189

156190
writeq_relaxed(reg, priv->reg_base + APPLE_DVFS_CMD);
@@ -275,7 +309,7 @@ static int apple_soc_cpufreq_init(struct cpufreq_policy *policy)
275309

276310
transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
277311
if (!transition_latency)
278-
transition_latency = CPUFREQ_ETERNAL;
312+
transition_latency = APPLE_DVFS_TRANSITION_TIMEOUT * NSEC_PER_USEC;
279313

280314
policy->cpuinfo.transition_latency = transition_latency;
281315
policy->dvfs_possible_from_any_cpu = true;

0 commit comments

Comments
 (0)