+ Rafael [corrected email addr]
On 14 August 2014 15:57, Ashwin Chaugule ashwin.chaugule@linaro.org wrote:
If the firmware supports CPPC natively in the firmware then we can use the ACPI defined semantics to access the CPPC specific registers.
Signed-off-by: Ashwin Chaugule ashwin.chaugule@linaro.org
drivers/cpufreq/Kconfig | 9 +++++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cppc.h | 4 +-- drivers/cpufreq/cppc_acpi.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 drivers/cpufreq/cppc_acpi.c
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index d8e8335..c5f3c0b 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -206,6 +206,15 @@ config CPPC_CPUFREQ (e.g. BMC) interpret and optimize it for power and performance in a platform specific manner.
+config CPPC_ACPI
bool "CPPC with ACPI accessors"
depends on ACPI && ACPI_PCC
default n
help
This driver implements the low level accessors to the registers as described
in the ACPI 5.1 spec. Select this driver if you know your platform supports CPPC
and PCC in the firmware.
menu "x86 CPU frequency scaling drivers" depends on X86 source "drivers/cpufreq/Kconfig.x86" diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index b392c8c..d49a999 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o
obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += cpufreq-cpu0.o obj-$(CONFIG_CPPC_CPUFREQ) += cppc.o +obj-$(CONFIG_CPPC_ACPI) += cppc_acpi.o
################################################################################## # x86 drivers. diff --git a/drivers/cpufreq/cppc.h b/drivers/cpufreq/cppc.h index 3adbd3d..a119c3b 100644 --- a/drivers/cpufreq/cppc.h +++ b/drivers/cpufreq/cppc.h @@ -175,7 +175,7 @@ struct cpc_funcs { };
extern struct cpc_funcs *cppc_func_ops; -extern u64 cpc_read64(struct cpc_register_resource *reg); -extern int cpc_write64(u64 val, struct cpc_register_resource *reg); +extern u64 cpc_read64(struct cpc_register_resource *reg, void __iomem *base_addr); +extern int cpc_write64(u64 val, struct cpc_register_resource *reg, void __iomem *base_addr);
#endif /* _CPPC_H */ diff --git a/drivers/cpufreq/cppc_acpi.c b/drivers/cpufreq/cppc_acpi.c new file mode 100644 index 0000000..1835fe7 --- /dev/null +++ b/drivers/cpufreq/cppc_acpi.c @@ -0,0 +1,80 @@ +/*
Copyright (C) 2014 Linaro Ltd.
Author: Ashwin Chaugule <ashwin.chaugule@linaro.org>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- */
+#include <linux/acpi.h>
+#include "cppc.h"
+static u32 acpi_get_highest_perf(struct cpudata *cpu) +{
struct cpc_register_resource *high_perf = &cpu->cpc_desc->cpc_regs[HIGHEST_PERF];
return cpc_read64(high_perf, cpu->pcc_comm_address);
+}
+static u64 acpi_get_ref_perf_ctr(struct cpudata *cpu) +{
struct cpc_register_resource *ref_perf = &cpu->cpc_desc->cpc_regs[REFERENCE_CTR];
return cpc_read64(ref_perf, cpu->pcc_comm_address);
+}
+static u32 acpi_get_lowest_perf(struct cpudata *cpu) +{
struct cpc_register_resource *low_perf = &cpu->cpc_desc->cpc_regs[LOWEST_PERF];
return cpc_read64(low_perf, cpu->pcc_comm_address);
+}
+static void acpi_set_desired_perf(struct cpudata *cpu, u32 val) +{
struct cpc_register_resource *desired_perf = &cpu->cpc_desc->cpc_regs[DESIRED_PERF];
cpc_write64(val, desired_perf, cpu->pcc_comm_address);
+}
+static u64 acpi_get_delivered_ctr(struct cpudata *cpu) +{
struct cpc_register_resource *delivered_ctr = &cpu->cpc_desc->cpc_regs[DELIVERED_CTR];
return cpc_read64(delivered_ctr, cpu->pcc_comm_address);
+}
+struct cpc_funcs acpi_cppc_func_ops = {
.pid_policy = {
.sample_rate_ms = 10,
.deadband = 0,
.setpoint = 97,
.p_gain_pct = 20,
.d_gain_pct = 0,
.i_gain_pct = 0,
},
.get_highest_perf = acpi_get_highest_perf,
.get_ref_perf_ctr = acpi_get_ref_perf_ctr,
.get_lowest_perf = acpi_get_lowest_perf,
.set_desired_perf = acpi_set_desired_perf,
.get_delivered_ctr = acpi_get_delivered_ctr,
+};
+static int __init acpi_cppc_init(void) +{
if (acpi_disabled)
return 0;
cppc_func_ops = &acpi_cppc_func_ops;
pr_info("Registered ACPI CPPC function ops\n");
return 0;
+} +early_initcall(acpi_cppc_init);
-- 1.9.1