Skip to content

Commit 028d1ae

Browse files
Merge patch series "RISC-V: ACPI: Enable CPPC based cpufreq support"
Sunil V L <sunilvl@ventanamicro.com> says: This series enables the support for "Collaborative Processor Performance Control (CPPC) on ACPI based RISC-V platforms. It depends on the encoding of CPPC registers as defined in RISC-V FFH spec [2]. CPPC is described in the ACPI spec [1]. RISC-V FFH spec required to enable this, is available at [2]. [1] - https://uefi.org/specs/ACPI/6.5/08_Processor_Configuration_and_Control.html#collaborative-processor-performance-control [2] - https://github.com/riscv-non-isa/riscv-acpi-ffh/releases/download/v1.0.0/riscv-ffh.pdf * b4-shazam-merge: RISC-V: defconfig: Enable CONFIG_ACPI_CPPC_CPUFREQ cpufreq: Move CPPC configs to common Kconfig and add RISC-V ACPI: RISC-V: Add CPPC driver Link: https://lore.kernel.org/r/20240208034414.22579-1-sunilvl@ventanamicro.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2 parents 01261e2 + 282b9df commit 028d1ae

File tree

5 files changed

+188
-26
lines changed

5 files changed

+188
-26
lines changed

arch/riscv/configs/defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
4444
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
4545
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
4646
CONFIG_CPUFREQ_DT=y
47+
CONFIG_ACPI_CPPC_CPUFREQ=m
4748
CONFIG_VIRTUALIZATION=y
4849
CONFIG_KVM=m
4950
CONFIG_ACPI=y

drivers/acpi/riscv/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
obj-y += rhct.o
33
obj-$(CONFIG_ACPI_PROCESSOR_IDLE) += cpuidle.o
4+
obj-$(CONFIG_ACPI_CPPC_LIB) += cppc.o

drivers/acpi/riscv/cppc.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Implement CPPC FFH helper routines for RISC-V.
4+
*
5+
* Copyright (C) 2024 Ventana Micro Systems Inc.
6+
*/
7+
8+
#include <acpi/cppc_acpi.h>
9+
#include <asm/csr.h>
10+
#include <asm/sbi.h>
11+
12+
#define SBI_EXT_CPPC 0x43505043
13+
14+
/* CPPC interfaces defined in SBI spec */
15+
#define SBI_CPPC_PROBE 0x0
16+
#define SBI_CPPC_READ 0x1
17+
#define SBI_CPPC_READ_HI 0x2
18+
#define SBI_CPPC_WRITE 0x3
19+
20+
/* RISC-V FFH definitions from RISC-V FFH spec */
21+
#define FFH_CPPC_TYPE(r) (((r) & GENMASK_ULL(63, 60)) >> 60)
22+
#define FFH_CPPC_SBI_REG(r) ((r) & GENMASK(31, 0))
23+
#define FFH_CPPC_CSR_NUM(r) ((r) & GENMASK(11, 0))
24+
25+
#define FFH_CPPC_SBI 0x1
26+
#define FFH_CPPC_CSR 0x2
27+
28+
struct sbi_cppc_data {
29+
u64 val;
30+
u32 reg;
31+
struct sbiret ret;
32+
};
33+
34+
static bool cppc_ext_present;
35+
36+
static int __init sbi_cppc_init(void)
37+
{
38+
if (sbi_spec_version >= sbi_mk_version(2, 0) &&
39+
sbi_probe_extension(SBI_EXT_CPPC) > 0) {
40+
pr_info("SBI CPPC extension detected\n");
41+
cppc_ext_present = true;
42+
} else {
43+
pr_info("SBI CPPC extension NOT detected!!\n");
44+
cppc_ext_present = false;
45+
}
46+
47+
return 0;
48+
}
49+
device_initcall(sbi_cppc_init);
50+
51+
static void sbi_cppc_read(void *read_data)
52+
{
53+
struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
54+
55+
data->ret = sbi_ecall(SBI_EXT_CPPC, SBI_CPPC_READ,
56+
data->reg, 0, 0, 0, 0, 0);
57+
}
58+
59+
static void sbi_cppc_write(void *write_data)
60+
{
61+
struct sbi_cppc_data *data = (struct sbi_cppc_data *)write_data;
62+
63+
data->ret = sbi_ecall(SBI_EXT_CPPC, SBI_CPPC_WRITE,
64+
data->reg, data->val, 0, 0, 0, 0);
65+
}
66+
67+
static void cppc_ffh_csr_read(void *read_data)
68+
{
69+
struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
70+
71+
switch (data->reg) {
72+
/* Support only TIME CSR for now */
73+
case CSR_TIME:
74+
data->ret.value = csr_read(CSR_TIME);
75+
data->ret.error = 0;
76+
break;
77+
default:
78+
data->ret.error = -EINVAL;
79+
break;
80+
}
81+
}
82+
83+
static void cppc_ffh_csr_write(void *write_data)
84+
{
85+
struct sbi_cppc_data *data = (struct sbi_cppc_data *)write_data;
86+
87+
data->ret.error = -EINVAL;
88+
}
89+
90+
/*
91+
* Refer to drivers/acpi/cppc_acpi.c for the description of the functions
92+
* below.
93+
*/
94+
bool cpc_ffh_supported(void)
95+
{
96+
return true;
97+
}
98+
99+
int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
100+
{
101+
struct sbi_cppc_data data;
102+
103+
if (WARN_ON_ONCE(irqs_disabled()))
104+
return -EPERM;
105+
106+
if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_SBI) {
107+
if (!cppc_ext_present)
108+
return -EINVAL;
109+
110+
data.reg = FFH_CPPC_SBI_REG(reg->address);
111+
112+
smp_call_function_single(cpu, sbi_cppc_read, &data, 1);
113+
114+
*val = data.ret.value;
115+
116+
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
117+
} else if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_CSR) {
118+
data.reg = FFH_CPPC_CSR_NUM(reg->address);
119+
120+
smp_call_function_single(cpu, cppc_ffh_csr_read, &data, 1);
121+
122+
*val = data.ret.value;
123+
124+
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
125+
}
126+
127+
return -EINVAL;
128+
}
129+
130+
int cpc_write_ffh(int cpu, struct cpc_reg *reg, u64 val)
131+
{
132+
struct sbi_cppc_data data;
133+
134+
if (WARN_ON_ONCE(irqs_disabled()))
135+
return -EPERM;
136+
137+
if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_SBI) {
138+
if (!cppc_ext_present)
139+
return -EINVAL;
140+
141+
data.reg = FFH_CPPC_SBI_REG(reg->address);
142+
data.val = val;
143+
144+
smp_call_function_single(cpu, sbi_cppc_write, &data, 1);
145+
146+
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
147+
} else if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_CSR) {
148+
data.reg = FFH_CPPC_CSR_NUM(reg->address);
149+
data.val = val;
150+
151+
smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1);
152+
153+
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
154+
}
155+
156+
return -EINVAL;
157+
}

drivers/cpufreq/Kconfig

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,4 +302,33 @@ config QORIQ_CPUFREQ
302302
which are capable of changing the CPU's frequency dynamically.
303303

304304
endif
305+
306+
config ACPI_CPPC_CPUFREQ
307+
tristate "CPUFreq driver based on the ACPI CPPC spec"
308+
depends on ACPI_PROCESSOR
309+
depends on ARM || ARM64 || RISCV
310+
select ACPI_CPPC_LIB
311+
help
312+
This adds a CPUFreq driver which uses CPPC methods
313+
as described in the ACPIv5.1 spec. CPPC stands for
314+
Collaborative Processor Performance Controls. It
315+
is based on an abstract continuous scale of CPU
316+
performance values which allows the remote power
317+
processor to flexibly optimize for power and
318+
performance. CPPC relies on power management firmware
319+
support for its operation.
320+
321+
If in doubt, say N.
322+
323+
config ACPI_CPPC_CPUFREQ_FIE
324+
bool "Frequency Invariance support for CPPC cpufreq driver"
325+
depends on ACPI_CPPC_CPUFREQ && GENERIC_ARCH_TOPOLOGY
326+
depends on ARM || ARM64 || RISCV
327+
default y
328+
help
329+
This extends frequency invariance support in the CPPC cpufreq driver,
330+
by using CPPC delivered and reference performance counters.
331+
332+
If in doubt, say N.
333+
305334
endmenu

drivers/cpufreq/Kconfig.arm

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,6 @@
33
# ARM CPU Frequency scaling drivers
44
#
55

6-
config ACPI_CPPC_CPUFREQ
7-
tristate "CPUFreq driver based on the ACPI CPPC spec"
8-
depends on ACPI_PROCESSOR
9-
select ACPI_CPPC_LIB
10-
help
11-
This adds a CPUFreq driver which uses CPPC methods
12-
as described in the ACPIv5.1 spec. CPPC stands for
13-
Collaborative Processor Performance Controls. It
14-
is based on an abstract continuous scale of CPU
15-
performance values which allows the remote power
16-
processor to flexibly optimize for power and
17-
performance. CPPC relies on power management firmware
18-
support for its operation.
19-
20-
If in doubt, say N.
21-
22-
config ACPI_CPPC_CPUFREQ_FIE
23-
bool "Frequency Invariance support for CPPC cpufreq driver"
24-
depends on ACPI_CPPC_CPUFREQ && GENERIC_ARCH_TOPOLOGY
25-
default y
26-
help
27-
This extends frequency invariance support in the CPPC cpufreq driver,
28-
by using CPPC delivered and reference performance counters.
29-
30-
If in doubt, say N.
31-
326
config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
337
tristate "Allwinner nvmem based SUN50I CPUFreq driver"
348
depends on ARCH_SUNXI

0 commit comments

Comments
 (0)