mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
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>
This commit is contained in:
commit
028d1aee1f
@ -44,6 +44,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
|
||||
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
|
||||
CONFIG_CPUFREQ_DT=y
|
||||
CONFIG_ACPI_CPPC_CPUFREQ=m
|
||||
CONFIG_VIRTUALIZATION=y
|
||||
CONFIG_KVM=m
|
||||
CONFIG_ACPI=y
|
||||
|
@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-y += rhct.o
|
||||
obj-$(CONFIG_ACPI_PROCESSOR_IDLE) += cpuidle.o
|
||||
obj-$(CONFIG_ACPI_CPPC_LIB) += cppc.o
|
||||
|
157
drivers/acpi/riscv/cppc.c
Normal file
157
drivers/acpi/riscv/cppc.c
Normal file
@ -0,0 +1,157 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Implement CPPC FFH helper routines for RISC-V.
|
||||
*
|
||||
* Copyright (C) 2024 Ventana Micro Systems Inc.
|
||||
*/
|
||||
|
||||
#include <acpi/cppc_acpi.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/sbi.h>
|
||||
|
||||
#define SBI_EXT_CPPC 0x43505043
|
||||
|
||||
/* CPPC interfaces defined in SBI spec */
|
||||
#define SBI_CPPC_PROBE 0x0
|
||||
#define SBI_CPPC_READ 0x1
|
||||
#define SBI_CPPC_READ_HI 0x2
|
||||
#define SBI_CPPC_WRITE 0x3
|
||||
|
||||
/* RISC-V FFH definitions from RISC-V FFH spec */
|
||||
#define FFH_CPPC_TYPE(r) (((r) & GENMASK_ULL(63, 60)) >> 60)
|
||||
#define FFH_CPPC_SBI_REG(r) ((r) & GENMASK(31, 0))
|
||||
#define FFH_CPPC_CSR_NUM(r) ((r) & GENMASK(11, 0))
|
||||
|
||||
#define FFH_CPPC_SBI 0x1
|
||||
#define FFH_CPPC_CSR 0x2
|
||||
|
||||
struct sbi_cppc_data {
|
||||
u64 val;
|
||||
u32 reg;
|
||||
struct sbiret ret;
|
||||
};
|
||||
|
||||
static bool cppc_ext_present;
|
||||
|
||||
static int __init sbi_cppc_init(void)
|
||||
{
|
||||
if (sbi_spec_version >= sbi_mk_version(2, 0) &&
|
||||
sbi_probe_extension(SBI_EXT_CPPC) > 0) {
|
||||
pr_info("SBI CPPC extension detected\n");
|
||||
cppc_ext_present = true;
|
||||
} else {
|
||||
pr_info("SBI CPPC extension NOT detected!!\n");
|
||||
cppc_ext_present = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(sbi_cppc_init);
|
||||
|
||||
static void sbi_cppc_read(void *read_data)
|
||||
{
|
||||
struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
|
||||
|
||||
data->ret = sbi_ecall(SBI_EXT_CPPC, SBI_CPPC_READ,
|
||||
data->reg, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void sbi_cppc_write(void *write_data)
|
||||
{
|
||||
struct sbi_cppc_data *data = (struct sbi_cppc_data *)write_data;
|
||||
|
||||
data->ret = sbi_ecall(SBI_EXT_CPPC, SBI_CPPC_WRITE,
|
||||
data->reg, data->val, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void cppc_ffh_csr_read(void *read_data)
|
||||
{
|
||||
struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
|
||||
|
||||
switch (data->reg) {
|
||||
/* Support only TIME CSR for now */
|
||||
case CSR_TIME:
|
||||
data->ret.value = csr_read(CSR_TIME);
|
||||
data->ret.error = 0;
|
||||
break;
|
||||
default:
|
||||
data->ret.error = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cppc_ffh_csr_write(void *write_data)
|
||||
{
|
||||
struct sbi_cppc_data *data = (struct sbi_cppc_data *)write_data;
|
||||
|
||||
data->ret.error = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refer to drivers/acpi/cppc_acpi.c for the description of the functions
|
||||
* below.
|
||||
*/
|
||||
bool cpc_ffh_supported(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
|
||||
{
|
||||
struct sbi_cppc_data data;
|
||||
|
||||
if (WARN_ON_ONCE(irqs_disabled()))
|
||||
return -EPERM;
|
||||
|
||||
if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_SBI) {
|
||||
if (!cppc_ext_present)
|
||||
return -EINVAL;
|
||||
|
||||
data.reg = FFH_CPPC_SBI_REG(reg->address);
|
||||
|
||||
smp_call_function_single(cpu, sbi_cppc_read, &data, 1);
|
||||
|
||||
*val = data.ret.value;
|
||||
|
||||
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
|
||||
} else if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_CSR) {
|
||||
data.reg = FFH_CPPC_CSR_NUM(reg->address);
|
||||
|
||||
smp_call_function_single(cpu, cppc_ffh_csr_read, &data, 1);
|
||||
|
||||
*val = data.ret.value;
|
||||
|
||||
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int cpc_write_ffh(int cpu, struct cpc_reg *reg, u64 val)
|
||||
{
|
||||
struct sbi_cppc_data data;
|
||||
|
||||
if (WARN_ON_ONCE(irqs_disabled()))
|
||||
return -EPERM;
|
||||
|
||||
if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_SBI) {
|
||||
if (!cppc_ext_present)
|
||||
return -EINVAL;
|
||||
|
||||
data.reg = FFH_CPPC_SBI_REG(reg->address);
|
||||
data.val = val;
|
||||
|
||||
smp_call_function_single(cpu, sbi_cppc_write, &data, 1);
|
||||
|
||||
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
|
||||
} else if (FFH_CPPC_TYPE(reg->address) == FFH_CPPC_CSR) {
|
||||
data.reg = FFH_CPPC_CSR_NUM(reg->address);
|
||||
data.val = val;
|
||||
|
||||
smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1);
|
||||
|
||||
return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
@ -302,4 +302,33 @@ config QORIQ_CPUFREQ
|
||||
which are capable of changing the CPU's frequency dynamically.
|
||||
|
||||
endif
|
||||
|
||||
config ACPI_CPPC_CPUFREQ
|
||||
tristate "CPUFreq driver based on the ACPI CPPC spec"
|
||||
depends on ACPI_PROCESSOR
|
||||
depends on ARM || ARM64 || RISCV
|
||||
select ACPI_CPPC_LIB
|
||||
help
|
||||
This adds a CPUFreq driver which uses CPPC methods
|
||||
as described in the ACPIv5.1 spec. CPPC stands for
|
||||
Collaborative Processor Performance Controls. It
|
||||
is based on an abstract continuous scale of CPU
|
||||
performance values which allows the remote power
|
||||
processor to flexibly optimize for power and
|
||||
performance. CPPC relies on power management firmware
|
||||
support for its operation.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
config ACPI_CPPC_CPUFREQ_FIE
|
||||
bool "Frequency Invariance support for CPPC cpufreq driver"
|
||||
depends on ACPI_CPPC_CPUFREQ && GENERIC_ARCH_TOPOLOGY
|
||||
depends on ARM || ARM64 || RISCV
|
||||
default y
|
||||
help
|
||||
This extends frequency invariance support in the CPPC cpufreq driver,
|
||||
by using CPPC delivered and reference performance counters.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
endmenu
|
||||
|
@ -3,32 +3,6 @@
|
||||
# ARM CPU Frequency scaling drivers
|
||||
#
|
||||
|
||||
config ACPI_CPPC_CPUFREQ
|
||||
tristate "CPUFreq driver based on the ACPI CPPC spec"
|
||||
depends on ACPI_PROCESSOR
|
||||
select ACPI_CPPC_LIB
|
||||
help
|
||||
This adds a CPUFreq driver which uses CPPC methods
|
||||
as described in the ACPIv5.1 spec. CPPC stands for
|
||||
Collaborative Processor Performance Controls. It
|
||||
is based on an abstract continuous scale of CPU
|
||||
performance values which allows the remote power
|
||||
processor to flexibly optimize for power and
|
||||
performance. CPPC relies on power management firmware
|
||||
support for its operation.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
config ACPI_CPPC_CPUFREQ_FIE
|
||||
bool "Frequency Invariance support for CPPC cpufreq driver"
|
||||
depends on ACPI_CPPC_CPUFREQ && GENERIC_ARCH_TOPOLOGY
|
||||
default y
|
||||
help
|
||||
This extends frequency invariance support in the CPPC cpufreq driver,
|
||||
by using CPPC delivered and reference performance counters.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
|
||||
tristate "Allwinner nvmem based SUN50I CPUFreq driver"
|
||||
depends on ARCH_SUNXI
|
||||
|
Loading…
Reference in New Issue
Block a user